// Global state and polling management if (typeof window.ChatManager === 'undefined') { window.ChatManager = (function() { let instance = null; let pollInterval = null; const state = { addedMessageIds: new Set(), messageQueue: new Set(), connectionState: { hasJoined: false, isConnected: true, lastMessageId: null, pollAttempts: 0 } }; function init(conversationId) { if (instance) { console.log('[ChatManager] Instance already exists, returning existing instance'); return instance; } console.log('[ChatManager] Initializing new instance for conversation:', conversationId); // Initialize message IDs from existing messages $('.message').each(function() { const messageId = $(this).data('message-id'); if (messageId) { state.addedMessageIds.add(messageId); state.connectionState.lastMessageId = Math.max(state.connectionState.lastMessageId || 0, messageId); console.log('[ChatManager] Initialized with existing message:', { messageId: messageId, lastMessageId: state.connectionState.lastMessageId }); } }); // Start polling for new messages startPolling(conversationId); instance = { state: state, cleanup: cleanup }; return instance; } function startPolling(conversationId) { console.log('[ChatManager] Starting polling for conversation:', conversationId); // Clear any existing polling if (pollInterval) { console.log('[ChatManager] Clearing existing polling interval'); clearInterval(pollInterval); } // Poll every 3 seconds pollInterval = setInterval(() => { console.log('[ChatManager] Polling interval triggered'); fetchNewMessages(conversationId); }, 3000); // Initial fetch console.log('[ChatManager] Performing initial message fetch'); fetchNewMessages(conversationId); } function fetchNewMessages(conversationId) { const url = `/conversations/${conversationId}/messages`; const params = new URLSearchParams(); if (state.connectionState.lastMessageId) { params.append('last_message_id', state.connectionState.lastMessageId); } console.log('[ChatManager] Fetching new messages:', { url: url, params: params.toString(), lastMessageId: state.connectionState.lastMessageId }); fetch(`${url}?${params.toString()}`) .then(response => response.json()) .then(data => { console.log('[ChatManager] Received messages response:', { success: data.success, messageCount: data.messages ? data.messages.length : 0, messages: data.messages }); if (data.success && data.messages) { state.connectionState.pollAttempts = 0; processNewMessages(data.messages); } }) .catch(error => { console.error('[ChatManager] Error fetching messages:', error); state.connectionState.pollAttempts++; // If we've had too many failed attempts, try to reconnect if (state.connectionState.pollAttempts > 5) { console.log('[ChatManager] Too many failed attempts, restarting polling'); startPolling(conversationId); } }); } function processNewMessages(messages) { console.log('[ChatManager] Processing new messages:', { messageCount: messages.length, currentLastMessageId: state.connectionState.lastMessageId, existingMessageIds: Array.from(state.addedMessageIds) }); messages.forEach(message => { console.log('[ChatManager] Processing message:', { messageId: message.id, alreadyAdded: state.addedMessageIds.has(message.id), currentLastMessageId: state.connectionState.lastMessageId }); if (!state.addedMessageIds.has(message.id)) { state.addedMessageIds.add(message.id); state.connectionState.lastMessageId = Math.max(state.connectionState.lastMessageId || 0, message.id); console.log('[ChatManager] Triggering new_message event for message:', message.id); // Trigger the new message event $(document).trigger('new_message', [message]); } else { console.log('[ChatManager] Skipping already added message:', message.id); } }); } function cleanup() { console.log('[ChatManager] Cleaning up polling'); if (pollInterval) { clearInterval(pollInterval); pollInterval = null; } instance = null; } return { getInstance: function(conversationId) { if (!instance) { instance = init(conversationId); } return instance; } }; })(); }