diff --git a/frontend-sba/composables/useWebSocket.ts b/frontend-sba/composables/useWebSocket.ts index 43bf1c9..8976553 100644 --- a/frontend-sba/composables/useWebSocket.ts +++ b/frontend-sba/composables/useWebSocket.ts @@ -139,6 +139,38 @@ export function useWebSocket() { reconnectionAttempts = 0 } + /** + * Force reconnect - clears the singleton and creates a fresh connection. + * Use this when the connection is in a bad state and normal reconnection isn't working. + */ + function forceReconnect() { + console.log('[WebSocket] Force reconnecting - clearing singleton') + + // Clear reconnection timer + if (reconnectionTimeout) { + clearTimeout(reconnectionTimeout) + reconnectionTimeout = null + } + + // Fully disconnect and destroy the socket instance + if (socketInstance) { + socketInstance.removeAllListeners() + socketInstance.disconnect() + socketInstance = null + } + + // Reset all state + isConnected.value = false + isConnecting.value = false + connectionError.value = null + reconnectionAttempts = 0 + + // Reconnect after a short delay + setTimeout(() => { + connect() + }, 100) + } + /** * Reconnect with exponential backoff */ @@ -473,8 +505,10 @@ export function useWebSocket() { // Watch for auth changes (not immediate - onMounted handles initial state) watch( () => authStore.isAuthenticated, - (authenticated) => { + (authenticated, oldValue) => { + console.log('[WebSocket] Auth changed:', oldValue, '->', authenticated) if (authenticated && !isConnected.value && !isConnecting.value) { + console.log('[WebSocket] Auth became true, connecting...') connect() startHeartbeat() } else if (!authenticated && isConnected.value) { @@ -489,9 +523,18 @@ export function useWebSocket() { // ============================================================================ // Initial connection on client-side mount (handles SSR hydration case) - onMounted(() => { + onMounted(async () => { + console.log('[WebSocket] onMounted - isAuthenticated:', authStore.isAuthenticated) + + // If not authenticated, try to check auth first (handles SSR hydration case) + if (!authStore.isAuthenticated) { + console.log('[WebSocket] Not authenticated on mount, checking auth...') + await authStore.checkAuth() + console.log('[WebSocket] After checkAuth - isAuthenticated:', authStore.isAuthenticated) + } + if (authStore.isAuthenticated && !isConnected.value && !isConnecting.value) { - console.log('[WebSocket] Auto-connecting on mount (already authenticated)') + console.log('[WebSocket] Auto-connecting on mount (authenticated)') connect() startHeartbeat() } @@ -519,5 +562,6 @@ export function useWebSocket() { // Actions connect, disconnect, + forceReconnect, } } diff --git a/frontend-sba/pages/games/[id].vue b/frontend-sba/pages/games/[id].vue index 2663749..1f7f01c 100755 --- a/frontend-sba/pages/games/[id].vue +++ b/frontend-sba/pages/games/[id].vue @@ -19,18 +19,32 @@ v-if="!isConnected" class="mb-4 bg-yellow-50 border-l-4 border-yellow-400 p-4 rounded-lg" > -
- {{ connectionStatus === 'connecting' ? 'Connecting to game server...' : 'Disconnected from server. Attempting to reconnect...' }} -
++ {{ connectionStatus === 'connecting' ? 'Connecting to game server...' : 'Disconnected from server. Attempting to reconnect...' }} +
+ ++ Auth: {{ authStore.isAuthenticated ? 'Yes' : 'No' }} | + Connecting: {{ isConnecting ? 'Yes' : 'No' }} | + Error: {{ connectionError || 'None' }} +
+Loading game...
+ ++ Auth: {{ authStore.isAuthenticated ? 'Yes' : 'No' }} | + Connected: {{ isConnected ? 'Yes' : 'No' }} | + Connecting: {{ isConnecting ? 'Yes' : 'No' }} +
++ Error: {{ connectionError || 'None' }} +
+