// Chat System Module // Handles chat functionality, message handling, and user authentication (function() { 'use strict'; AppModules.require('api', 'ui-controls'); AppModules.register('chat'); // Initialize chat system function initializeChat() { AppLogger.log('Initializing chat system...'); // Get user ID first API.getUserId() .then(data => { AppLogger.log('Chat initialized with user:', AppState.userId, AppState.isAdmin ? '(admin)' : ''); // Show admin toast if applicable if (AppState.isAdmin) { UIControls.showToast('Admin mode activated'); } // Set up nickname handling const nicknameInput = document.getElementById('nickname'); if (nicknameInput) { // Load saved nickname const savedNickname = localStorage.getItem('chatNickname'); if (savedNickname) { nicknameInput.value = savedNickname; } // Handle nickname changes UIControls.DOMUtils.addEvent(nicknameInput, 'change', function() { const nickname = this.value.trim(); localStorage.setItem('chatNickname', nickname); AppState.nickname = nickname; }); } // Set up message input handling const messageInput = document.getElementById('messageInput'); if (messageInput) { // Enter key to send message UIControls.DOMUtils.addEvent(messageInput, 'keypress', function(e) { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); sendMessage(); } }); // Typing indicator UIControls.DOMUtils.addEvent(messageInput, 'input', function() { handleTypingIndicator(); }); } // Set up send button const sendButton = document.querySelector('.chat-input button') || document.querySelector('#messageInput').nextElementSibling; if (sendButton && sendButton.tagName === 'BUTTON') { UIControls.DOMUtils.addEvent(sendButton, 'click', sendMessage); } // Start polling for messages startMessagePolling(); // Send initial heartbeat API.sendHeartbeat(); AppLogger.log('Chat system initialized successfully'); }) .catch(error => { AppLogger.error('Failed to initialize chat:', error); UIControls.showToast('Failed to initialize chat'); }); } // Send message functionality function sendMessage() { const messageInput = document.getElementById('messageInput'); const nicknameInput = document.getElementById('nickname'); const message = messageInput?.value?.trim() || ''; const nickname = nicknameInput?.value?.trim() || ''; if (!nickname) { if (nicknameInput) { nicknameInput.style.borderColor = 'var(--dodgers-red)'; nicknameInput.focus(); } UIControls.showToast('Please enter a nickname'); setTimeout(() => { if (nicknameInput) nicknameInput.style.borderColor = '#e0e0e0'; }, 2000); return; } if (!message) { return; // Just return quietly for empty message } // Send message via API API.sendMessage(nickname, message) .then(data => { if (data.success) { if (messageInput) messageInput.value = ''; AppState.nickname = nickname; // Message will be added automatically by polling } else if (data.error) { UIControls.showToast(data.error); UIControls.updateConnectionStatus(false); } }) .catch(error => { AppLogger.error('Error sending message:', error); UIControls.showToast('Failed to send message'); UIControls.updateConnectionStatus(false); }); } // Delete message (admin only) function deleteMessage(messageId) { if (!AppState.isAdmin) return; if (!confirm('Delete this message?')) return; API.deleteMessage(messageId) .then(data => { if (data.success) { removeMessageFromUI(messageId); UIControls.showToast('Message deleted'); } else { UIControls.showToast('Failed to delete message'); } }) .catch(error => { AppLogger.error('Error deleting message:', error); UIControls.showToast('Failed to delete message'); }); } // Ban user (admin only) function banUser(userId) { if (!AppState.isAdmin) return; if (!confirm('Ban this user from chat?')) return; API.banUser(userId) .then(data => { if (data.success) { UIControls.showToast('User banned'); } else { UIControls.showToast('Failed to ban user'); } }) .catch(error => { AppLogger.error('Error banning user:', error); UIControls.showToast('Failed to ban user'); }); } // Clear chat (admin only) function clearChat() { if (!AppState.isAdmin) return; if (!confirm('Clear all chat messages?')) return; API.clearChat() .then(data => { if (data.success) { clearMessagesUI(); UIControls.showToast('Chat cleared'); AppState.lastMessageId = ''; API.sendHeartbeat(); // Force refresh all users } else { UIControls.showToast('Failed to clear chat'); } }) .catch(error => { AppLogger.error('Error clearing chat:', error); UIControls.showToast('Failed to clear chat'); }); } // Message polling system function startMessagePolling() { // Poll for new messages setInterval(fetchMessages, AppConfig.api.chatPollInterval); // Send heartbeat periodically setInterval(API.sendHeartbeat, AppConfig.api.heartbeatInterval); // Initial fetch fetchMessages(); } // Fetch and display messages function fetchMessages() { API.fetchMessages() .then(data => { if (data.success) { // Handle initial load or message updates if (data.all_messages !== null) { // Initial load or forced refresh (like after admin clear) handleInitialMessageLoad(data); } else { // Incremental updates handleNewMessages(data.messages); } // Check for admin clear if (data.message_count === 0 && AppState.allMessages.length > 0) { handleChatCleared(); } // Update last message ID if (AppState.allMessages.length > 0) { AppState.lastMessageId = AppState.allMessages[AppState.allMessages.length - 1].id; } UIControls.updateConnectionStatus(true); } }) .catch(error => { AppLogger.error('Error fetching messages:', error); UIControls.updateConnectionStatus(false); }); } // Handle initial message load function handleInitialMessageLoad(data) { AppState.allMessages = data.all_messages || []; displayAllMessages(); } // Handle new messages function handleNewMessages(messages) { if (!messages || messages.length === 0) return; messages.forEach(msg => { appendMessage(msg); // Show notification if chat is collapsed and message is not from current user if (AppState.chatCollapsed && msg.user_id !== AppState.userId) { AppState.unreadCount++; UIControls.updateNotificationBadge(); UIControls.playNotificationSound(); } }); } // Handle chat cleared by admin function handleChatCleared() { const chatMessages = document.getElementById('chatMessages'); if (chatMessages) { chatMessages.innerHTML = '
'; } AppState.allMessages = []; AppState.lastMessageId = ''; } // Typing indicator system function handleTypingIndicator() { const messageInput = document.getElementById('messageInput'); if (!messageInput) return; const hasContent = messageInput.value.length > 0; if (hasContent && !AppState.isTyping) { AppState.isTyping = true; } clearTimeout(AppState.typingTimer); AppState.typingTimer = setTimeout(() => { AppState.isTyping = false; }, AppConfig.chat.typingTimeout); } // UI manipulation functions function displayAllMessages() { const chatMessages = document.getElementById('chatMessages'); if (!chatMessages) return; if (AppState.allMessages.length === 0) { chatMessages.innerHTML = '