Logic: Capped reconnection (5m) and manual retry UI

This commit is contained in:
Timo
2026-04-22 09:17:01 +02:00
parent 8b8dc9e546
commit d9e2d6aa77
3 changed files with 55 additions and 7 deletions
+36 -3
View File
@@ -12,6 +12,8 @@ let currentTabTitle = null; // New: for Smart Matching
let logs = [];
let history = []; // New: for Action History
let reconnectTimer = null;
let reconnectStartTime = null; // New: track when reconnection started
let reconnectFailed = false; // New: true if we hit the 5-min cap
// Force Sync Coordination
let isForceSyncInitiator = false;
@@ -58,8 +60,11 @@ async function connect() {
if (socket && (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING)) return;
if (!navigator.onLine) {
addLog('Browser is offline. Waiting...', 'warn');
broadcastConnectionStatus('offline');
return;
}
if (reconnectFailed) return; // Wait for manual retry
if (!peerId) peerId = await getPeerId();
const settings = await getSettings();
@@ -110,6 +115,8 @@ async function connect() {
reconnectDelay = 1000;
addLog('WebSocket Connection Opened', 'success');
broadcastConnectionStatus('connected');
reconnectStartTime = null;
reconnectFailed = false;
// Socket.IO Handshake: Send "40" to join default namespace
socket.send('40');
@@ -180,7 +187,15 @@ function broadcastConnectionStatus(status) {
}
function updateBadgeStatus() {
if (currentTabId) {
const status = socket ? (socket.readyState === WebSocket.OPEN ? 'connected' : (isConnecting || socket.readyState === WebSocket.CONNECTING ? 'connecting' : 'disconnected')) : 'disconnected';
if (reconnectFailed) {
chrome.action.setBadgeText({ text: 'ERR' });
chrome.action.setBadgeBackgroundColor({ color: '#ef4444' });
} else if (status === 'connecting') {
chrome.action.setBadgeText({ text: '...' });
chrome.action.setBadgeBackgroundColor({ color: '#fbbf24' });
} else if (currentTabId) {
chrome.action.setBadgeText({ text: 'ON' });
chrome.action.setBadgeBackgroundColor({ color: '#22c55e' });
} else {
@@ -204,7 +219,17 @@ function showNotification(senderName, action) {
}
function scheduleReconnect() {
if (reconnectTimer) return; // Already scheduled
if (reconnectTimer || reconnectFailed) return;
if (!reconnectStartTime) reconnectStartTime = Date.now();
// Check 5 minute cap (300,000ms)
if (Date.now() - reconnectStartTime > 300000) {
reconnectFailed = true;
addLog('Reconnection failed after 5 minutes. Please try again manually.', 'error');
broadcastConnectionStatus('reconnect_failed');
return;
}
reconnectTimer = setTimeout(() => {
reconnectTimer = null;
@@ -378,9 +403,17 @@ chrome.alarms.onAlarm.addListener((alarm) => {
// --- Extension Message Listeners ---
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if (message.type === 'CONNECT') {
reconnectFailed = false;
reconnectStartTime = null;
connect();
} else if (message.type === 'RETRY_CONNECT') {
reconnectFailed = false;
reconnectStartTime = null;
reconnectDelay = 1000;
connect();
} else if (message.type === 'GET_STATUS') {
const status = socket ? (socket.readyState === WebSocket.OPEN ? 'connected' : (isConnecting || socket.readyState === WebSocket.CONNECTING ? 'connecting' : 'disconnected')) : 'disconnected';
let status = socket ? (socket.readyState === WebSocket.OPEN ? 'connected' : (isConnecting || socket.readyState === WebSocket.CONNECTING ? 'connecting' : 'disconnected')) : 'disconnected';
if (reconnectFailed) status = 'reconnect_failed';
sendResponse({ status, peerId, peers: currentRoom ? currentRoom.peers : [] });
// Global return true at the end handles this
} else if (message.type === 'LEAVE_ROOM') {
+2 -1
View File
@@ -277,9 +277,10 @@
</div>
<label>Connection Status</label>
<div id="connStatus" class="info-card" style="display:flex; align-items:center;">
<div id="connStatus" class="info-card" style="display:flex; align-items:center; gap: 10px;">
<span id="connDot" class="status-dot status-offline"></span>
<span id="connText" style="flex:1;">Disconnected</span>
<button id="retryBtn" class="secondary" style="display:none; width: auto; padding: 4px 8px; font-size: 10px; margin: 0;">RETRY</button>
<button id="copyLogs" class="btn secondary" style="width: auto; padding: 4px 10px; font-size: 11px;">Copy Logs</button>
</div>
+17 -3
View File
@@ -35,7 +35,8 @@ const elements = {
createRoomBtn: document.getElementById('createRoomBtn'),
publicRooms: document.getElementById('publicRooms'),
refreshRooms: document.getElementById('refreshRooms'),
roomError: document.getElementById('roomError')
roomError: document.getElementById('roomError'),
retryBtn: document.getElementById('retryBtn')
};
let localPeerId = null;
@@ -183,8 +184,17 @@ async function populateTabs(providedPeers = null) {
function applyConnectionStatus(status) {
const connected = status === 'connected';
const connecting = status === 'connecting';
elements.connDot.className = 'status-dot ' + (connected ? 'status-online' : 'status-offline');
elements.connText.textContent = connected ? 'Connected' : (connecting ? 'Connecting...' : 'Disconnected');
const failed = status === 'reconnect_failed';
elements.connDot.className = 'status-dot ' + (connected ? 'status-online' : (failed ? 'status-offline' : (connecting ? 'status-online' : 'status-offline')));
// Custom colors for states
if (connecting) elements.connDot.style.background = '#fbbf24';
else if (failed) elements.connDot.style.background = '#ef4444';
else elements.connDot.style.background = '';
elements.connText.textContent = connected ? 'Connected' : (connecting ? 'Connecting...' : (failed ? 'Failed' : 'Disconnected'));
elements.retryBtn.style.display = failed ? 'block' : 'none';
}
function updateHistory(history) {
@@ -349,6 +359,10 @@ elements.refreshRooms.addEventListener('click', () => {
chrome.runtime.sendMessage({ type: 'GET_ROOM_LIST' });
});
elements.retryBtn.addEventListener('click', () => {
chrome.runtime.sendMessage({ type: 'RETRY_CONNECT' });
});
elements.targetTab.addEventListener('change', async () => {
await chrome.storage.sync.set({ targetTabId: elements.targetTab.value });
});