diff --git a/zebra-report/zebra-spaces.html b/zebra-report/zebra-spaces.html index 3c85355..0a69770 100644 --- a/zebra-report/zebra-spaces.html +++ b/zebra-report/zebra-spaces.html @@ -817,6 +817,17 @@ function hex(buf){ const u8=buf instanceof Uint8Array?buf:new Uint8Array(buf); r function shortHex(s){ return s.slice(0,4)+'…'+s.slice(-4); } const logEl = $('log'); +/* Global error handler — runtime errors used to die silently (no + * stack trace anywhere), so a broken button just stopped working + * with no signal-server visibility. Now every uncaught exception + * AND unhandled-promise-rejection forwards to CLIENT_LOG as kind=err. */ +window.addEventListener('error', (ev) => { + try { logLine('err', 'JS error: '+ev.message+' at '+(ev.filename||'?')+':'+(ev.lineno||'?')); } catch(_){} +}); +window.addEventListener('unhandledrejection', (ev) => { + try { logLine('err', 'JS unhandled: '+(ev.reason && (ev.reason.message || ev.reason.toString()) || 'unknown')); } catch(_){} +}); + function logLine(kind, msg){ const d=document.createElement('div'); d.className='log-line '+(kind||''); d.innerHTML=''+new Date().toLocaleTimeString()+' '+msg.replace(/[&<>]/g,c=>({'&':'&','<':'<','>':'>'}[c])); @@ -4864,6 +4875,7 @@ $('btn-copy-share').addEventListener('click', async () => { * the same channel cameras/screens use so the room sees the choice */ renderGamesColumn(); $('btn-leave').addEventListener('click', async () => { + logLine('', 'leave-button: click fired'); wantConnected = false; roomMachines.call.send('LEAVE'); /* explicit leave wipes the auto-rejoin state — user said 'out' */ @@ -4932,8 +4944,8 @@ logLine('', 'ready — pick a handle, type a rendezvous code, enter the space');