mirror of
https://github.com/Shik3i/KoalaSync.git
synced 2026-07-27 12:29:35 +00:00
Fix custom server reconnection and reconnect strategy
- Fix: CONNECT/RETRY_CONNECT always force-disconnect before reconnecting (prevents JOIN_ROOM going to official server when custom is selected) - Add forceDisconnect() helper: clears socket, eventQueue, episodeLobby, expectedAcksCount, broadcast status, persists cleanup to storage - Fix: save useCustomServer to storage on Join Room click (no race condition) - Fix: trigger RETRY_CONNECT on server mode toggle and custom URL change - Fix: show error when Custom selected but no URL entered (no silent fallback) - Fix: button label changed to 'Join / Create Room' in all 6 locales - Rewrite scheduleReconnect() for two-phase strategy: Phase 1 (aggressive): 500ms-5s backoff, max 20 attempts or 5 minutes Phase 2 (slow): retry every 5 minutes indefinitely, never give up - Persist reconnectAttempts/reconnectStartTime/reconnectFailed to session storage - Remove 'reconnect_failed' status; slow mode shows as 'reconnecting' with retry button - Add scheduleReconnect() call on offline path to continue retry cycle
This commit is contained in:
+72
-58
@@ -55,7 +55,7 @@ function ensureState() {
|
||||
chrome.storage.session.get([
|
||||
'logs', 'history', 'currentRoom', 'lastActionState',
|
||||
'eventQueue', 'isForceSyncInitiator', 'forceSyncAcks',
|
||||
'forceSyncDeadline', 'reconnectFailed', 'reconnectStartTime', 'currentTabId', 'currentTabTitle',
|
||||
'forceSyncDeadline', 'reconnectFailed', 'reconnectStartTime', 'reconnectAttempts', 'currentTabId', 'currentTabTitle',
|
||||
'episodeLobby', 'localSeq', 'lastSeqBySender', 'expectedAcksCount'
|
||||
], (data) => {
|
||||
clearTimeout(storageTimeout);
|
||||
@@ -79,6 +79,7 @@ function ensureState() {
|
||||
}
|
||||
if (data.reconnectFailed !== undefined) reconnectFailed = data.reconnectFailed;
|
||||
if (data.reconnectStartTime) reconnectStartTime = data.reconnectStartTime;
|
||||
if (data.reconnectAttempts !== undefined) reconnectAttempts = data.reconnectAttempts;
|
||||
|
||||
// Recover Force Sync Timeout
|
||||
if (data.forceSyncDeadline) {
|
||||
@@ -271,6 +272,50 @@ function addLog(message, type = 'info') {
|
||||
}
|
||||
|
||||
// --- WebSocket Client ---
|
||||
function forceDisconnect() {
|
||||
if (reconnectTimer) {
|
||||
clearTimeout(reconnectTimer);
|
||||
reconnectTimer = null;
|
||||
}
|
||||
if (episodeLobbyTimeout) {
|
||||
clearTimeout(episodeLobbyTimeout);
|
||||
episodeLobbyTimeout = null;
|
||||
}
|
||||
episodeLobby = null;
|
||||
if (forceSyncTimeout) {
|
||||
clearTimeout(forceSyncTimeout);
|
||||
forceSyncTimeout = null;
|
||||
}
|
||||
if (socket) {
|
||||
socket.onopen = null;
|
||||
socket.onmessage = null;
|
||||
socket.onclose = null;
|
||||
socket.onerror = null;
|
||||
socket.close();
|
||||
socket = null;
|
||||
}
|
||||
isConnecting = false;
|
||||
isNamespaceJoined = false;
|
||||
isForceSyncInitiator = false;
|
||||
expectedAcksCount = 0;
|
||||
forceSyncAcks.clear();
|
||||
eventQueue = [];
|
||||
chrome.storage.session.set({
|
||||
isForceSyncInitiator: false,
|
||||
forceSyncAcks: [],
|
||||
forceSyncDeadline: null,
|
||||
expectedAcksCount: 0,
|
||||
eventQueue: [],
|
||||
episodeLobby: null
|
||||
}).catch(() => {});
|
||||
if (currentRoom) {
|
||||
currentRoom.peers = [];
|
||||
if (storageInitialized) chrome.storage.session.set({ currentRoom });
|
||||
chrome.runtime.sendMessage({ type: 'PEER_UPDATE', peers: [] }).catch(() => {});
|
||||
}
|
||||
broadcastConnectionStatus('disconnected');
|
||||
}
|
||||
|
||||
async function connect() {
|
||||
if (isConnecting) return;
|
||||
isConnecting = true;
|
||||
@@ -303,11 +348,7 @@ async function connect() {
|
||||
addLog('Browser is offline. Waiting...', 'warn');
|
||||
broadcastConnectionStatus('offline');
|
||||
isConnecting = false;
|
||||
return;
|
||||
}
|
||||
|
||||
if (reconnectFailed) {
|
||||
isConnecting = false;
|
||||
scheduleReconnect();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -353,10 +394,10 @@ async function connect() {
|
||||
// --- Phase 5: Event Listeners ---
|
||||
socket.onopen = () => {
|
||||
reconnectAttempts = 0;
|
||||
addLog('WebSocket Connection Opened', 'success');
|
||||
reconnectStartTime = null;
|
||||
reconnectFailed = false;
|
||||
chrome.storage.session.set({ reconnectFailed: false });
|
||||
addLog('WebSocket Connection Opened', 'success');
|
||||
chrome.storage.session.set({ reconnectFailed: false, reconnectAttempts: 0, reconnectStartTime: null }).catch(() => {});
|
||||
isNamespaceJoined = false;
|
||||
socket.send('40');
|
||||
};
|
||||
@@ -452,13 +493,10 @@ function broadcastConnectionStatus(status) {
|
||||
|
||||
function updateBadgeStatus() {
|
||||
const isConnected = socket && socket.readyState === WebSocket.OPEN && isNamespaceJoined;
|
||||
const isReconnecting = !isConnected && reconnectAttempts > 0 && !reconnectFailed;
|
||||
const isReconnecting = !isConnected && reconnectAttempts > 0;
|
||||
const status = isConnected ? 'connected' : (isConnecting || (socket && socket.readyState === WebSocket.CONNECTING) ? 'connecting' : (isReconnecting ? 'reconnecting' : 'disconnected'));
|
||||
|
||||
if (reconnectFailed) {
|
||||
chrome.action.setBadgeText({ text: 'ERR' });
|
||||
chrome.action.setBadgeBackgroundColor({ color: '#ef4444' });
|
||||
} else if (status === 'reconnecting') {
|
||||
if (status === 'reconnecting') {
|
||||
chrome.action.setBadgeText({ text: '...' });
|
||||
chrome.action.setBadgeBackgroundColor({ color: '#f59e0b' });
|
||||
} else if (status === 'connecting') {
|
||||
@@ -517,36 +555,27 @@ function showNotification(senderName, action) {
|
||||
function scheduleReconnect() {
|
||||
if (reconnectTimer) return;
|
||||
|
||||
if (reconnectFailed) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!reconnectStartTime) reconnectStartTime = Date.now();
|
||||
|
||||
// Check 5 minute cap (300,000ms)
|
||||
if (Date.now() - reconnectStartTime > 300000) {
|
||||
reconnectFailed = true;
|
||||
chrome.storage.session.set({ reconnectFailed: true });
|
||||
addLog('Reconnection failed after 5 minutes.', 'error');
|
||||
broadcastConnectionStatus('reconnect_failed');
|
||||
return;
|
||||
}
|
||||
|
||||
const elapsed = Date.now() - reconnectStartTime;
|
||||
reconnectAttempts++;
|
||||
|
||||
// Cap at max attempts to prevent infinite loops
|
||||
if (reconnectAttempts > MAX_RECONNECT_ATTEMPTS) {
|
||||
if (!reconnectFailed && (elapsed > 300000 || reconnectAttempts > MAX_RECONNECT_ATTEMPTS)) {
|
||||
reconnectFailed = true;
|
||||
chrome.storage.session.set({ reconnectFailed: true });
|
||||
addLog('Reconnection failed after max attempts.', 'error');
|
||||
broadcastConnectionStatus('reconnect_failed');
|
||||
return;
|
||||
addLog('Switching to slow reconnect mode (every 5 minutes)', 'warn');
|
||||
}
|
||||
|
||||
// Aggressive reconnect: 500ms base, cap at 5s, no exponential growth beyond that
|
||||
const delay = Math.min(_RECONNECT_BASE_DELAY * Math.pow(1.5, reconnectAttempts - 1), _RECONNECT_MAX_DELAY);
|
||||
const delay = reconnectFailed
|
||||
? 300000
|
||||
: Math.min(_RECONNECT_BASE_DELAY * Math.pow(1.5, reconnectAttempts - 1), _RECONNECT_MAX_DELAY);
|
||||
|
||||
addLog(`Reconnect in ${Math.round(delay)}ms (attempt ${reconnectAttempts})`, 'warn');
|
||||
if (reconnectFailed) {
|
||||
addLog(`Slow reconnect in 5min (attempt ${reconnectAttempts})`, 'info');
|
||||
} else {
|
||||
addLog(`Reconnect in ${Math.round(delay)}ms (attempt ${reconnectAttempts})`, 'warn');
|
||||
}
|
||||
|
||||
chrome.storage.session.set({ reconnectFailed, reconnectAttempts, reconnectStartTime }).catch(() => {});
|
||||
|
||||
reconnectTimer = setTimeout(() => {
|
||||
reconnectTimer = null;
|
||||
@@ -1196,42 +1225,26 @@ async function handleAsyncMessage(message, sender, sendResponse) {
|
||||
reconnectFailed = false;
|
||||
reconnectStartTime = null;
|
||||
reconnectAttempts = 0;
|
||||
chrome.storage.session.set({ reconnectFailed: false });
|
||||
chrome.storage.session.set({ reconnectFailed: false, reconnectAttempts: 0, reconnectStartTime: null });
|
||||
const settings = await getSettings();
|
||||
if (settings.roomId) {
|
||||
leaveOldRoomIfSwitching(settings.roomId);
|
||||
}
|
||||
if (socket && socket.readyState === WebSocket.OPEN && isNamespaceJoined) {
|
||||
if (settings.roomId) {
|
||||
emit(EVENTS.JOIN_ROOM, {
|
||||
roomId: settings.roomId,
|
||||
password: settings.password,
|
||||
peerId,
|
||||
username: settings.username,
|
||||
tabTitle: currentTabTitle,
|
||||
protocolVersion: PROTOCOL_VERSION
|
||||
});
|
||||
}
|
||||
} else {
|
||||
connect();
|
||||
}
|
||||
forceDisconnect();
|
||||
connect();
|
||||
sendResponse({ status: 'ok' });
|
||||
} else if (message.type === 'RETRY_CONNECT') {
|
||||
reconnectFailed = false;
|
||||
reconnectStartTime = null;
|
||||
reconnectAttempts = 0;
|
||||
if (reconnectTimer) {
|
||||
clearTimeout(reconnectTimer);
|
||||
reconnectTimer = null;
|
||||
}
|
||||
chrome.storage.session.set({ reconnectFailed: false });
|
||||
chrome.storage.session.set({ reconnectFailed: false, reconnectAttempts: 0, reconnectStartTime: null });
|
||||
forceDisconnect();
|
||||
connect();
|
||||
sendResponse({ status: 'ok' });
|
||||
} else if (message.type === 'GET_STATUS') {
|
||||
const isConnected = socket && socket.readyState === WebSocket.OPEN && isNamespaceJoined;
|
||||
const isReconnecting = !isConnected && reconnectAttempts > 0 && !reconnectFailed;
|
||||
const isReconnecting = !isConnected && reconnectAttempts > 0;
|
||||
let status = isConnected ? 'connected' : (isConnecting || (socket && socket.readyState === WebSocket.CONNECTING) ? 'connecting' : (isReconnecting ? 'reconnecting' : 'disconnected'));
|
||||
if (reconnectFailed) status = 'reconnect_failed';
|
||||
sendResponse({
|
||||
status,
|
||||
peerId,
|
||||
@@ -1239,7 +1252,8 @@ async function handleAsyncMessage(message, sender, sendResponse) {
|
||||
lastActionState,
|
||||
targetTabId: currentTabId,
|
||||
episodeLobby: episodeLobby,
|
||||
reconnectAttempts
|
||||
reconnectAttempts,
|
||||
reconnectSlowMode: reconnectFailed
|
||||
});
|
||||
} else if (message.type === 'LEAVE_ROOM') {
|
||||
emit(EVENTS.LEAVE_ROOM, { peerId });
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"LABEL_PASSWORD_TOOLTIP": "Optionales Passwort, um den Raumzugang zu beschränken",
|
||||
"PLACEHOLDER_PASSWORD": "Raum-Passwort (optional)",
|
||||
"PLACEHOLDER_PASSWORD_TOOLTIP": "Passwort für den Raum (leer lassen, wenn keines vorhanden)",
|
||||
"BTN_JOIN_ROOM": "Raum beitreten",
|
||||
"BTN_JOIN_ROOM": "Raum beitreten / erstellen",
|
||||
"BTN_JOIN_ROOM_TOOLTIP": "Mit dem Raum verbinden",
|
||||
"LABEL_PUBLIC_ROOMS": "Öffentliche Räume",
|
||||
"LABEL_PUBLIC_ROOMS_TOOLTIP": "Liste der öffentlich verfügbaren Räume auf diesem Server",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"LABEL_PASSWORD_TOOLTIP": "Optional password to restrict room access",
|
||||
"PLACEHOLDER_PASSWORD": "Room Password (optional)",
|
||||
"PLACEHOLDER_PASSWORD_TOOLTIP": "Password for the room (leave empty if none)",
|
||||
"BTN_JOIN_ROOM": "Join Room",
|
||||
"BTN_JOIN_ROOM": "Join / Create Room",
|
||||
"BTN_JOIN_ROOM_TOOLTIP": "Connect to the room",
|
||||
"LABEL_PUBLIC_ROOMS": "Public Rooms",
|
||||
"LABEL_PUBLIC_ROOMS_TOOLTIP": "List of publicly available rooms on this server",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"LABEL_PASSWORD_TOOLTIP": "Contraseña opcional para restringir el acceso a la sala",
|
||||
"PLACEHOLDER_PASSWORD": "Contraseña de la sala (opcional)",
|
||||
"PLACEHOLDER_PASSWORD_TOOLTIP": "Contraseña para la sala (dejar vacío si no hay)",
|
||||
"BTN_JOIN_ROOM": "Unirse a la sala",
|
||||
"BTN_JOIN_ROOM": "Unirse / Crear sala",
|
||||
"BTN_JOIN_ROOM_TOOLTIP": "Conectarse a la sala",
|
||||
"LABEL_PUBLIC_ROOMS": "Salas públicas",
|
||||
"LABEL_PUBLIC_ROOMS_TOOLTIP": "Lista de salas públicas disponibles en este servidor",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"LABEL_PASSWORD_TOOLTIP": "Mot de passe optionnel pour restreindre l'accès au salon",
|
||||
"PLACEHOLDER_PASSWORD": "Mot de passe du salon (optionnel)",
|
||||
"PLACEHOLDER_PASSWORD_TOOLTIP": "Mot de passe du salon (laisser vide si aucun)",
|
||||
"BTN_JOIN_ROOM": "Rejoindre le salon",
|
||||
"BTN_JOIN_ROOM": "Rejoindre / Créer le salon",
|
||||
"BTN_JOIN_ROOM_TOOLTIP": "Se connecter au salon",
|
||||
"LABEL_PUBLIC_ROOMS": "Salons publics",
|
||||
"LABEL_PUBLIC_ROOMS_TOOLTIP": "Liste des salons publics disponibles sur ce serveur",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"LABEL_PASSWORD_TOOLTIP": "Senha opcional para restringir o acesso à sala",
|
||||
"PLACEHOLDER_PASSWORD": "Senha da sala (opcional)",
|
||||
"PLACEHOLDER_PASSWORD_TOOLTIP": "Senha para a sala (deixe em branco se não houver)",
|
||||
"BTN_JOIN_ROOM": "Entrar na sala",
|
||||
"BTN_JOIN_ROOM": "Entrar / Criar sala",
|
||||
"BTN_JOIN_ROOM_TOOLTIP": "Conectar à sala",
|
||||
"LABEL_PUBLIC_ROOMS": "Salas públicas",
|
||||
"LABEL_PUBLIC_ROOMS_TOOLTIP": "Lista de salas públicas disponíveis neste servidor",
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
"LABEL_PASSWORD_TOOLTIP": "Дополнительный пароль для ограничения доступа к комнате",
|
||||
"PLACEHOLDER_PASSWORD": "Пароль комнаты (опционально)",
|
||||
"PLACEHOLDER_PASSWORD_TOOLTIP": "Пароль от комнаты (оставьте пустым, если его нет)",
|
||||
"BTN_JOIN_ROOM": "Войти в комнату",
|
||||
"BTN_JOIN_ROOM": "Войти / Создать комнату",
|
||||
"BTN_JOIN_ROOM_TOOLTIP": "Подключиться к комнате",
|
||||
"LABEL_PUBLIC_ROOMS": "Публичные комнаты",
|
||||
"LABEL_PUBLIC_ROOMS_TOOLTIP": "Список публично доступных комнат на этом сервере",
|
||||
|
||||
+29
-11
@@ -59,6 +59,7 @@ let localPeerId = null;
|
||||
let lastPeersJson = null;
|
||||
let lastKnownPeers = [];
|
||||
let isDevTabVisible = false;
|
||||
let reconnectSlowMode = false;
|
||||
let joinBtnTimeout = null;
|
||||
let forceSyncResetTimer = null;
|
||||
let popupIntervals = [];
|
||||
@@ -128,6 +129,7 @@ async function init() {
|
||||
}
|
||||
if (res) {
|
||||
localPeerId = res.peerId;
|
||||
reconnectSlowMode = res.reconnectSlowMode || false;
|
||||
applyConnectionStatus(res.status);
|
||||
updatePeerList(res.peers);
|
||||
lastKnownPeers = res.peers || [];
|
||||
@@ -671,10 +673,9 @@ function applyConnectionStatus(status) {
|
||||
const connected = status === 'connected';
|
||||
const connecting = status === 'connecting';
|
||||
const reconnecting = status === 'reconnecting';
|
||||
const failed = status === 'reconnect_failed';
|
||||
|
||||
if (elements.connDot) {
|
||||
elements.connDot.className = 'status-dot ' + (connected ? 'status-online' : (failed ? 'status-offline' : ((connecting || reconnecting) ? 'status-online' : 'status-offline')));
|
||||
elements.connDot.className = 'status-dot ' + (connected ? 'status-online' : ((connecting || reconnecting) ? 'status-online' : 'status-offline'));
|
||||
|
||||
if (reconnecting) {
|
||||
elements.connDot.style.background = '#f59e0b';
|
||||
@@ -682,7 +683,7 @@ function applyConnectionStatus(status) {
|
||||
} else if (connecting) {
|
||||
elements.connDot.style.background = '#fbbf24';
|
||||
elements.connDot.style.boxShadow = '0 0 8px #fbbf24';
|
||||
} else if (failed) {
|
||||
} else if (!connected) {
|
||||
elements.connDot.style.background = '#ef4444';
|
||||
elements.connDot.style.boxShadow = 'none';
|
||||
} else {
|
||||
@@ -692,15 +693,15 @@ function applyConnectionStatus(status) {
|
||||
}
|
||||
|
||||
if (elements.connText) {
|
||||
elements.connText.textContent = connected ? getMessage('STATUS_CONNECTED') : (reconnecting ? getMessage('STATUS_RECONNECTING') : (connecting ? getMessage('STATUS_CONNECTING') : (failed ? getMessage('STATUS_FAILED') : getMessage('STATUS_DISCONNECTED'))));
|
||||
elements.connText.textContent = connected ? getMessage('STATUS_CONNECTED') : (reconnecting ? getMessage('STATUS_RECONNECTING') : (connecting ? getMessage('STATUS_CONNECTING') : getMessage('STATUS_DISCONNECTED')));
|
||||
}
|
||||
if (elements.retryBtn) {
|
||||
elements.retryBtn.style.display = failed ? 'block' : 'none';
|
||||
elements.retryBtn.style.display = reconnecting && reconnectSlowMode ? 'block' : 'none';
|
||||
}
|
||||
|
||||
if (elements.joinBtn) {
|
||||
if (connecting || reconnecting) {
|
||||
elements.joinBtn.disabled = true;
|
||||
elements.joinBtn.disabled = !reconnectSlowMode;
|
||||
elements.joinBtn.textContent = connecting ? getMessage('BTN_STATE_JOINING') : getMessage('BTN_STATE_RECONNECTING');
|
||||
} else {
|
||||
elements.joinBtn.disabled = false;
|
||||
@@ -858,9 +859,12 @@ function setServerMode(custom) {
|
||||
elements.serverOfficial.classList.toggle('active', !custom);
|
||||
elements.serverCustom.classList.toggle('active', custom);
|
||||
elements.serverUrl.style.display = custom ? 'block' : 'none';
|
||||
chrome.storage.sync.get(['useCustomServer'], (data) => {
|
||||
chrome.storage.sync.get(['useCustomServer', 'serverUrl'], (data) => {
|
||||
if (data.useCustomServer !== custom) {
|
||||
chrome.storage.sync.set({ useCustomServer: custom });
|
||||
if (!custom || data.serverUrl) {
|
||||
chrome.runtime.sendMessage({ type: 'RETRY_CONNECT' });
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -919,6 +923,9 @@ elements.serverUrl.addEventListener('change', () => {
|
||||
elements.serverUrl.value = url;
|
||||
chrome.storage.sync.set({ serverUrl: url });
|
||||
}
|
||||
if (elements.serverCustom.classList.contains('active') && url) {
|
||||
chrome.runtime.sendMessage({ type: 'RETRY_CONNECT' });
|
||||
}
|
||||
});
|
||||
|
||||
elements.tabs.forEach(btn => {
|
||||
@@ -993,6 +1000,12 @@ elements.joinBtn.addEventListener('click', async () => {
|
||||
const useCustom = elements.serverCustom.classList.contains('active');
|
||||
|
||||
// Proactive URL Validation
|
||||
if (useCustom && !serverUrl) {
|
||||
showError(getMessage('ERR_INVALID_SERVER_URL'));
|
||||
elements.joinBtn.disabled = false;
|
||||
elements.joinBtn.textContent = getMessage('BTN_JOIN_ROOM');
|
||||
return;
|
||||
}
|
||||
if (useCustom && serverUrl) {
|
||||
try {
|
||||
const urlToCheck = serverUrl.includes('://') ? serverUrl : 'ws://' + serverUrl;
|
||||
@@ -1008,7 +1021,7 @@ elements.joinBtn.addEventListener('click', async () => {
|
||||
const roomId = roomIdInput || Math.random().toString(36).substring(2, 8).toUpperCase();
|
||||
const password = elements.password.value;
|
||||
|
||||
await chrome.storage.sync.set({ serverUrl, roomId, password });
|
||||
await chrome.storage.sync.set({ serverUrl, roomId, password, useCustomServer: useCustom });
|
||||
elements.roomId.value = roomId;
|
||||
|
||||
// Tell background to connect
|
||||
@@ -1338,20 +1351,25 @@ chrome.runtime.onMessage.addListener((msg) => {
|
||||
updatePeerList(msg.peers);
|
||||
if (msg.peers) detectPeerChanges(msg.peers);
|
||||
} else if (msg.type === 'CONNECTION_STATUS') {
|
||||
applyConnectionStatus(msg.status);
|
||||
if (msg.status !== 'reconnecting') {
|
||||
applyConnectionStatus(msg.status);
|
||||
reconnectSlowMode = false;
|
||||
}
|
||||
if (msg.status === 'connected') {
|
||||
chrome.runtime.sendMessage({ type: 'GET_STATUS' }, (res) => {
|
||||
if (res && res.peers) updatePeerList(res.peers);
|
||||
if (res && res.lastActionState) updateLastActionUI(res.lastActionState, res.peers);
|
||||
});
|
||||
}
|
||||
if (msg.status === 'disconnected' || msg.status === 'reconnect_failed') {
|
||||
if (msg.status === 'disconnected') {
|
||||
elements.joinBtn.disabled = false;
|
||||
elements.joinBtn.textContent = 'Join Room';
|
||||
elements.joinBtn.textContent = getMessage('BTN_JOIN_ROOM');
|
||||
}
|
||||
if (msg.status === 'reconnecting') {
|
||||
chrome.runtime.sendMessage({ type: 'GET_STATUS' }, (res) => {
|
||||
if (chrome.runtime.lastError) return;
|
||||
if (res && res.reconnectSlowMode !== undefined) reconnectSlowMode = res.reconnectSlowMode;
|
||||
applyConnectionStatus(msg.status);
|
||||
if (res && res.reconnectAttempts !== undefined) {
|
||||
if (elements.connText) {
|
||||
elements.connText.textContent = `Reconnecting... (${res.reconnectAttempts})`;
|
||||
|
||||
Reference in New Issue
Block a user