From 5bde1757d6d75714959124545928480a518fe5fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mats=20T=C3=B6rnberg?= Date: Tue, 22 Sep 2026 11:17:05 +0200 Subject: [PATCH] Require a nickname before joining and add a quick-start help modal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit New visitors (no nickname in localStorage) get a blocking welcome modal instead of a silently-generated guest-N name, so everyone in a room has a name they actually chose. It doubles as quick-start help (join a channel, mic/deafen/share shortcuts, drag-to-reposition on the spatial map) reachable any time via the new ? button. The sidebar nick field no longer falls back to a random name when cleared — it now just rejects the blank edit. Co-Authored-By: Claude Sonnet 5 --- public/app.js | 46 ++++++++++++++++++++++++++++++++++++++++------ public/index.html | 25 +++++++++++++++++++++++++ public/style.css | 25 +++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 6 deletions(-) diff --git a/public/app.js b/public/app.js index 61b259d..9cd05c5 100644 --- a/public/app.js +++ b/public/app.js @@ -40,6 +40,7 @@ const els = { meAvatar: $('#me-avatar'), mic: $('#btn-mic'), deafen: $('#btn-deafen'), reconnectBanner: $('#reconnect-banner'), reconnectText: $('#reconnect-text'), mxPanel: $('#mx-panel'), mxMessages: $('#mx-messages'), mxInput: $('#mx-input'), + welcomeBackdrop: $('#welcome-backdrop'), welcomeNick: $('#welcome-nick'), welcomeNickError: $('#welcome-nick-error'), }; // --------------------------------------------------------------------------- @@ -1280,16 +1281,13 @@ $('#btn-settings').onclick = openSettings; els.nick.value = S.name; els.nick.addEventListener('change', () => { - S.name = els.nick.value.trim() || `guest-${Math.random().toString(36).slice(2, 6)}`; + const trimmed = els.nick.value.trim(); + if (!trimmed) { els.nick.value = S.name; return; } // nickname can't be blanked out + S.name = trimmed; els.nick.value = S.name; localStorage.setItem(LS_NAME, S.name); setAvatar(els.meAvatar, S.name, S.myId || 'me'); }); -if (!S.name) { - S.name = `guest-${Math.random().toString(36).slice(2, 6)}`; - els.nick.value = S.name; - localStorage.setItem(LS_NAME, S.name); -} setAvatar(els.meAvatar, S.name, 'me'); document.querySelectorAll('.channel.voice').forEach((el) => { @@ -1375,3 +1373,39 @@ $('#ice-save').onclick = () => { $('#modal-backdrop').classList.add('hidden'); toast(enabled ? 'Custom ICE saved — rejoin to apply' : 'Reverted to server ICE — rejoin to apply', 'ok'); }; + +// --------------------------------------------------------------------------- +// welcome modal — required nickname + quick-start info +// --------------------------------------------------------------------------- +let welcomeRequired = false; +function openWelcome(required) { + welcomeRequired = required; + els.welcomeNick.value = S.name; + els.welcomeNick.classList.remove('invalid'); + els.welcomeNickError.classList.add('hidden'); + els.welcomeBackdrop.classList.remove('hidden'); + els.welcomeNick.focus(); +} +function closeWelcome() { els.welcomeBackdrop.classList.add('hidden'); } +function submitWelcome() { + const trimmed = els.welcomeNick.value.trim(); + if (!trimmed) { + els.welcomeNick.classList.add('invalid'); + els.welcomeNickError.classList.remove('hidden'); + els.welcomeNick.focus(); + return; + } + S.name = trimmed; + els.nick.value = S.name; + localStorage.setItem(LS_NAME, S.name); + setAvatar(els.meAvatar, S.name, S.myId || 'me'); + closeWelcome(); +} +$('#welcome-continue').onclick = submitWelcome; +els.welcomeNick.addEventListener('keydown', (ev) => { if (ev.key === 'Enter') submitWelcome(); }); +els.welcomeBackdrop.onclick = (ev) => { + if (ev.target === els.welcomeBackdrop && !welcomeRequired) closeWelcome(); +}; +$('#btn-help').onclick = () => openWelcome(false); + +if (!S.name) openWelcome(true); diff --git a/public/index.html b/public/index.html index d4e9d30..582d797 100644 --- a/public/index.html +++ b/public/index.html @@ -52,6 +52,7 @@ + @@ -98,6 +99,30 @@ + + +