const $ = (id) => document.getElementById(id); const connectSection = $('connect-section'); const roomSection = $('room-section'); const serverUrlInput = $('server-url'); const connectBtn = $('connect-btn'); const roomControls = $('room-controls'); const inRoom = $('in-room'); const createBtn = $('create-btn'); const codeInput = $('code-input'); const joinBtn = $('join-btn'); const disconnectBtn = $('disconnect-btn'); const roomCodeEl = $('room-code'); const peerStatusEl = $('peer-status'); const errorMsg = $('error-msg'); function showError(text) { errorMsg.textContent = text; errorMsg.classList.remove('hidden'); setTimeout(() => errorMsg.classList.add('hidden'), 3000); } function showRoomView(code, hasPeer) { roomControls.classList.add('hidden'); inRoom.classList.remove('hidden'); roomCodeEl.textContent = code; peerStatusEl.textContent = hasPeer ? 'Peer connected' : 'Waiting for peer...'; peerStatusEl.className = 'peer-status' + (hasPeer ? ' connected' : ''); } connectBtn.addEventListener('click', () => { const url = serverUrlInput.value.trim(); if (!url) return; connectBtn.disabled = true; connectBtn.textContent = 'Connecting...'; chrome.runtime.sendMessage({ type: 'connect', url }); }); createBtn.addEventListener('click', () => { chrome.runtime.sendMessage({ type: 'create_room' }); }); joinBtn.addEventListener('click', () => { const code = codeInput.value.trim(); if (!/^\d{6}$/.test(code)) { showError('Enter a 6-digit code'); return; } chrome.runtime.sendMessage({ type: 'join_room', code }); }); codeInput.addEventListener('keydown', (e) => { if (e.key === 'Enter') joinBtn.click(); }); disconnectBtn.addEventListener('click', () => { chrome.runtime.sendMessage({ type: 'disconnect' }); roomSection.classList.add('hidden'); connectSection.classList.remove('hidden'); roomControls.classList.remove('hidden'); inRoom.classList.add('hidden'); connectBtn.disabled = false; connectBtn.textContent = 'Connect'; }); chrome.runtime.onMessage.addListener((msg) => { switch (msg.type) { case 'ws_status': if (msg.status === 'connected') { connectSection.classList.add('hidden'); roomSection.classList.remove('hidden'); } else { connectSection.classList.remove('hidden'); roomSection.classList.add('hidden'); connectBtn.disabled = false; connectBtn.textContent = 'Connect'; if (msg.status === 'error') showError('Could not connect to server'); } break; case 'created': showRoomView(msg.code, false); break; case 'joined': showRoomView(msg.code, msg.memberCount > 1); break; case 'peer_joined': peerStatusEl.textContent = 'Peer connected'; peerStatusEl.className = 'peer-status connected'; break; case 'peer_left': peerStatusEl.textContent = 'Peer disconnected'; peerStatusEl.className = 'peer-status'; break; case 'error': showError(msg.message); break; } }); // Restore state when popup opens chrome.storage.local.get(['serverUrl'], ({ serverUrl }) => { if (serverUrl) serverUrlInput.value = serverUrl; }); chrome.runtime.sendMessage({ type: 'get_state' }, (state) => { if (!state) return; if (state.connectState === 'connected') { connectSection.classList.add('hidden'); roomSection.classList.remove('hidden'); if (state.roomCode) showRoomView(state.roomCode, false); } });