const socket = io(); // UI Elements const statusBadge = document.getElementById('status-badge'); const qrContainer = document.getElementById('qr-container'); const activityLog = document.getElementById('activity-log'); const groupsTableBody = document.getElementById('groups-table-body'); const appsTableBody = document.getElementById('apps-table-body'); const inviteModal = document.getElementById('invite-modal'); const inviteLinkInput = document.getElementById('invite-link-input'); // Tab Switching document.querySelectorAll('.nav-btn').forEach(btn => { btn.addEventListener('click', (e) => { document.querySelectorAll('.nav-btn').forEach(b => b.classList.remove('active')); document.querySelectorAll('.tab-pane').forEach(p => p.classList.remove('active')); e.target.classList.add('active'); document.getElementById(e.target.dataset.tab).classList.add('active'); if (e.target.dataset.tab === 'groups') { fetchGroups(); } if (e.target.dataset.tab === 'apps') { fetchApps(); } }); }); // Logging function logActivity(msg, type = 'info') { const entry = document.createElement('p'); entry.className = `log-entry ${type}`; const time = new Date().toLocaleTimeString(); entry.textContent = `[${time}] ${msg}`; activityLog.prepend(entry); } // Socket Events socket.on('status', (data) => { updateStatus(data.ready); if (data.qr && !data.ready) renderQR(data.qr); }); socket.on('qr', (qr) => { renderQR(qr); logActivity('New QR code generated', 'system'); }); socket.on('ready', () => { updateStatus(true); qrContainer.innerHTML = '

✅ Connected

Session is active and authenticated.

'; logActivity('Client successfully authenticated and ready', 'success'); }); socket.on('disconnected', (reason) => { updateStatus(false); logActivity(`Disconnected: ${reason}`, 'error'); }); socket.on('incoming_message', (msg) => { logActivity(`Msg from ${msg.from}: ${msg.body.substring(0, 50)}...`, 'info'); }); function updateStatus(isReady) { if (isReady) { statusBadge.textContent = 'Connected'; statusBadge.className = 'badge success'; } else { statusBadge.textContent = 'Disconnected'; statusBadge.className = 'badge error'; } } function renderQR(qrText) { qrContainer.innerHTML = ''; const qr = qrcode(0, 'L'); qr.addData(qrText); qr.make(); qrContainer.innerHTML = qr.createImgTag(5); } // Groups Tab functionality async function fetchGroups() { groupsTableBody.innerHTML = 'Loading...'; try { const res = await fetch('api/groups'); const data = await res.json(); if (!data.success) { groupsTableBody.innerHTML = `Error: ${data.error || 'Not connected'}`; return; } if (data.groups.length === 0) { groupsTableBody.innerHTML = 'No groups found.'; return; } groupsTableBody.innerHTML = ''; data.groups.forEach(g => { const tr = document.createElement('tr'); tr.innerHTML = ` ${g.name}
${g.id} ${g.participants} `; groupsTableBody.appendChild(tr); }); } catch (e) { groupsTableBody.innerHTML = `Fetch failed.`; } } document.getElementById('btn-refresh-groups').addEventListener('click', fetchGroups); // Connected Apps functionality async function fetchApps() { appsTableBody.innerHTML = 'Loading...'; try { const res = await fetch('api/apps'); const data = await res.json(); if (!data.success) { appsTableBody.innerHTML = `Error fetching apps`; return; } if (data.apps.length === 0) { appsTableBody.innerHTML = 'No apps connected yet. Send a message to see an app appear here!'; return; } appsTableBody.innerHTML = ''; data.apps.sort((a, b) => new Date(b.lastSeen) - new Date(a.lastSeen)).forEach(app => { const tr = document.createElement('tr'); tr.innerHTML = ` ${app.name} ${app.messageCount} ${new Date(app.lastSeen).toLocaleString()} ${app.lastIp} `; appsTableBody.appendChild(tr); }); } catch (e) { appsTableBody.innerHTML = `Fetch failed.`; } } document.getElementById('btn-refresh-apps').addEventListener('click', fetchApps); // Create Group document.getElementById('create-group-form').addEventListener('submit', async (e) => { e.preventDefault(); const btn = e.target.querySelector('button'); btn.textContent = 'Creating...'; btn.disabled = true; const title = document.getElementById('new-group-name').value; const participant = document.getElementById('new-group-participant').value; try { const res = await fetch('api/groups/create', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ title, initialParticipants: [participant] }) }); const data = await res.json(); if (data.success) { alert('Group created successfully! ID: ' + data.groupId); fetchGroups(); e.target.reset(); } else { alert('Error: ' + data.error); } } catch (err) { alert('Failed to create group.'); } finally { btn.textContent = 'Create Group'; btn.disabled = false; } }); // Invite Link Modal window.getInviteLink = async (groupId) => { try { const res = await fetch('api/groups/invite', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ groupId }) }); const data = await res.json(); if (data.success) { inviteLinkInput.value = data.inviteLink; inviteModal.classList.add('active'); } else { alert('Failed to get invite link: ' + data.error); } } catch (err) { alert('Request failed.'); } }; document.querySelector('.close-modal').addEventListener('click', () => { inviteModal.classList.remove('active'); }); document.getElementById('btn-copy-link').addEventListener('click', () => { inviteLinkInput.select(); document.execCommand('copy'); alert('Copied to clipboard!'); }); // Test Message document.getElementById('test-msg-form').addEventListener('submit', async (e) => { e.preventDefault(); const btn = e.target.querySelector('button'); const resultDiv = document.getElementById('test-result'); btn.textContent = 'Sending...'; btn.disabled = true; resultDiv.textContent = ''; const to = document.getElementById('test-to').value; const message = document.getElementById('test-body').value; try { const res = await fetch('api/send-message', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ to, message }) }); const data = await res.json(); if (data.success) { resultDiv.innerHTML = `✅ Sent successfully (ID: ${data.messageId})`; document.getElementById('test-body').value = ''; } else { resultDiv.innerHTML = `❌ ${data.error}`; } } catch (err) { resultDiv.innerHTML = `❌ Request failed.`; } finally { btn.textContent = 'Send Message'; btn.disabled = false; } });