import { config } from "./config.js"; import { waha } from "./waha.js"; import { ui, elements } from "./ui.js"; import { websocket } from "./websocket.js"; import { compensateMessageOrdering, formatTime } from "./utils.js"; let chatsState = []; let activeChatState = null; // Initialize app when DOM is ready document.addEventListener('DOMContentLoaded', () => { setupEventListeners(); fetchChats(); checkWahaStatus(); initWebSocket(); }); function setupEventListeners() { elements.refreshChatsBtn.addEventListener('click', () => { elements.refreshChatsBtn.classList.add('spinning'); fetchChats().finally(() => { setTimeout(() => { elements.refreshChatsBtn.classList.remove('spinning'); }, 600); }); }); elements.chatSearch.addEventListener('input', (e) => { const query = e.target.value.toLowerCase(); const filtered = chatsState.filter(chat => chat.name.toLowerCase().includes(query) ); ui.renderChatList(filtered, activeChatState, selectChat); }); elements.messageForm.addEventListener('submit', (e) => { e.preventDefault(); sendMessage(); }); elements.backToSidebarBtn.addEventListener('click', () => { elements.sidebar.classList.remove('hidden'); elements.activeChatContainer.classList.add('hidden'); }); elements.settingsIconBtn.addEventListener('click', openSettings); elements.closeSettingsBtn.addEventListener('click', () => ui.toggleModal(false)); elements.cancelSettingsBtn.addEventListener('click', () => ui.toggleModal(false)); elements.saveSettingsBtn.addEventListener('click', saveSettings); } function initWebSocket() { websocket.connect((data) => { console.log('[WS] Received event:', data.event, data); const ev = data.event; if (ev === 'message' || ev === 'message.any' || ev === 'message.ack') { handleIncomingMessage(data.payload); } }); } function normalizeChatId(raw) { if (!raw) return null; if (typeof raw === 'object') { return raw._serialized || raw.user || JSON.stringify(raw); } return raw; } function handleIncomingMessage(msg) { if (!msg) return; console.log('[WS] handleIncomingMessage payload:', msg); const rawChatId = msg.chatId || msg.from || (msg.chat && msg.chat.id); const msgChatId = normalizeChatId(rawChatId); if (!msgChatId) { console.warn('[WS] Could not resolve chatId from payload:', msg); return; } console.log('[WS] Resolved msgChatId:', msgChatId, '| activeChatState:', activeChatState?.id); if (activeChatState && activeChatState.id === msgChatId) { const msgId = normalizeChatId(msg.id) || msg.id; const exists = document.getElementById(msgId); if (!exists) { ui.appendSingleMessage({ ...msg, chatId: msgChatId }, activeChatState.name); ui.scrollToBottom(); } } const chatIndex = chatsState.findIndex(c => c.id === msgChatId); if (chatIndex !== -1) { const chat = chatsState[chatIndex]; chat.lastMessage = msg.body || msg.text || 'Media message'; chat.timestamp = msg.timestamp ? (msg.timestamp * 1000) : Date.now(); if (!msg.fromMe && (!activeChatState || activeChatState.id !== msgChatId)) { chat.unreadCount = (chat.unreadCount || 0) + 1; } chatsState.sort((a, b) => { const tA = new Date(a.timestamp).getTime(); const tB = new Date(b.timestamp).getTime(); return tB - tA; }); ui.renderChatList(chatsState, activeChatState, selectChat); } else { fetchChats(); } } async function fetchChats() { const userInfo = await waha.getMyInfo(); elements.loggedUserName.textContent = userInfo.pushName; elements.userIcon.innerText = userInfo.pushName[0]; elements.chatsLoader.classList.remove('hidden'); try { chatsState = await waha.getChats(); ui.renderChatList(chatsState, activeChatState, selectChat); } catch (error) { console.error('Failed to load chats:', error); elements.chatList.innerHTML = `
Connection to WAHA failed.
Ensure WAHA server is running and CORS is enabled, or click Settings to configure.