Smart disconnect + human-readable room IDs + expanded word lists

- Add currentServerUrl tracking: only disconnect/reconnect when server URL actually
  changes, otherwise reuse existing connection and just switch rooms
- Add resolveServerUrl() helper for consistent URL resolution across handlers
- forceDisconnect() now resets currentServerUrl to null
- CONNECT and WEB_JOIN_REQUEST handlers: smart comparison before reconnecting
- Add generateRoomId(): human-readable 'ADJECTIVE-NOUN-Number' format (e.g. HAPPY-KOALA-16)
- Replace Math.random() room IDs with generateRoomId() in joinBtn and handleCreateRoom()
- Expand USERNAME_ADJECTIVES: +16 words (Turbo, Zen, Pixel, Cyber, Solar, etc.)
- Expand USERNAME_NOUNS: +12 words (Yeti, Goblin, Pirate, Ninja, Wizard, Storm, etc.)
- Add emoji mappings for all new words
This commit is contained in:
Timo
2026-06-01 13:29:02 +02:00
parent f2669ed769
commit a1f921407c
3 changed files with 65 additions and 8 deletions
+37 -4
View File
@@ -138,6 +138,7 @@ let reconnectTimer = null;
let reconnectStartTime = null;
let reconnectFailed = false;
let reconnectAttempts = 0;
let currentServerUrl = null;
const MAX_RECONNECT_ATTEMPTS = 20;
const _RECONNECT_BASE_DELAY = 500;
const _RECONNECT_MAX_DELAY = 5000;
@@ -272,6 +273,10 @@ function addLog(message, type = 'info') {
}
// --- WebSocket Client ---
function resolveServerUrl(settings) {
return (settings.serverUrl && settings.useCustomServer) ? settings.serverUrl : OFFICIAL_SERVER_URL;
}
function forceDisconnect() {
if (reconnectTimer) {
clearTimeout(reconnectTimer);
@@ -294,6 +299,7 @@ function forceDisconnect() {
socket.close();
socket = null;
}
currentServerUrl = null;
isConnecting = false;
isNamespaceJoined = false;
isForceSyncInitiator = false;
@@ -377,6 +383,8 @@ async function connect() {
addLog(`Connecting to ${isCustomServer ? finalUrl : 'Official Server'}... (attempt ${reconnectAttempts + 1})`, 'info');
currentServerUrl = finalUrl;
// --- Phase 4: WebSocket Init ---
try {
const url = new URL(finalUrl);
@@ -1230,8 +1238,20 @@ async function handleAsyncMessage(message, sender, sendResponse) {
if (settings.roomId) {
leaveOldRoomIfSwitching(settings.roomId);
}
forceDisconnect();
connect();
const desiredUrl = resolveServerUrl(settings);
if (desiredUrl !== currentServerUrl || !socket || socket.readyState !== WebSocket.OPEN || !isNamespaceJoined) {
if (desiredUrl !== currentServerUrl) forceDisconnect();
connect();
} else if (settings.roomId) {
emit(EVENTS.JOIN_ROOM, {
roomId: settings.roomId,
password: settings.password,
peerId,
username: settings.username,
tabTitle: currentTabTitle,
protocolVersion: PROTOCOL_VERSION
});
}
sendResponse({ status: 'ok' });
} else if (message.type === 'RETRY_CONNECT') {
reconnectFailed = false;
@@ -1306,8 +1326,21 @@ async function handleAsyncMessage(message, sender, sendResponse) {
chrome.storage.session.set({ reconnectFailed: false, reconnectAttempts: 0, reconnectStartTime: null });
broadcastConnectionStatus('connecting');
leaveOldRoomIfSwitching(roomId);
forceDisconnect();
connect();
const settings = await getSettings();
const desiredUrl = resolveServerUrl(settings);
if (desiredUrl !== currentServerUrl || !socket || socket.readyState !== WebSocket.OPEN || !isNamespaceJoined) {
if (desiredUrl !== currentServerUrl) forceDisconnect();
connect();
} else {
emit(EVENTS.JOIN_ROOM, {
roomId,
password,
peerId,
username: settings.username,
tabTitle: currentTabTitle,
protocolVersion: PROTOCOL_VERSION
});
}
addLog(`Joining room via link: ${roomId}`, 'info');
sendResponse({ status: 'ok' });
});
+10 -3
View File
@@ -1,6 +1,6 @@
import { EVENTS, OFFICIAL_LANDING_PAGE_URL } from './shared/constants.js';
import { BLACKLIST_DOMAINS } from './shared/blacklist.js';
import { getAvatarForName, generateUsername } from './shared/names.js';
import { getAvatarForName, generateUsername, USERNAME_ADJECTIVES, USERNAME_NOUNS } from './shared/names.js';
import { loadLocale, translateDOM, getMessage } from './i18n.js';
@@ -1018,7 +1018,7 @@ elements.joinBtn.addEventListener('click', async () => {
}
}
const roomId = roomIdInput || Math.random().toString(36).substring(2, 8).toUpperCase();
const roomId = roomIdInput || generateRoomId();
let password = elements.password.value;
if (isCreating && !password) {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
@@ -1048,6 +1048,13 @@ elements.leaveBtn.addEventListener('click', async () => {
updateUI(null, null);
});
function generateRoomId() {
const adj = USERNAME_ADJECTIVES[Math.floor(Math.random() * USERNAME_ADJECTIVES.length)];
const noun = USERNAME_NOUNS[Math.floor(Math.random() * USERNAME_NOUNS.length)];
const num = Math.floor(Math.random() * 99) + 1;
return `${adj.toUpperCase()}-${noun.toUpperCase()}-${num}`;
}
function handleCreateRoom() {
const secureGenerateId = (length = 6) => {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
@@ -1055,7 +1062,7 @@ function handleCreateRoom() {
self.crypto.getRandomValues(array);
return Array.from(array, byte => chars[byte % chars.length]).join('');
};
const roomId = secureGenerateId();
const roomId = generateRoomId();
const password = secureGenerateId();
elements.roomId.value = roomId;
elements.password.value = password;