document.addEventListener('DOMContentLoaded', function () { // متغیرهای وضعیت let currentRoomId = null; let lastMessageId = 0; let messagePollInterval = null; let roomPollInterval = null; // 🟢 متغیر قفل برای جلوگیری از دریافت پیام‌های تکراری (Race Condition) let isFetchingMessages = false; // المان‌های DOM const UI = { roomList: document.getElementById('room-list'), noChatSelected: document.getElementById('no-chat-selected'), chatHeader: document.getElementById('active-chat-header'), chatTitle: document.getElementById('active-chat-title'), messages: document.getElementById('chat-messages'), inputArea: document.getElementById('chat-input-area'), form: document.getElementById('chat-form'), input: document.getElementById('chat-input'), indicator: document.getElementById('polling-indicator') }; // گرفتن لیست چت‌ها از سرور async function fetchRooms() { try { const res = await fetch(window.CHAT_CONFIG.apiUrlRooms); const data = await res.json(); renderRooms(data.rooms); } catch (e) { console.error("Failed to fetch rooms:", e); } } // رندر کردن لیست چت‌ها function renderRooms(rooms) { if (rooms.length === 0) { UI.roomList.innerHTML = '

No active chats found.

'; return; } UI.roomList.innerHTML = rooms.map(room => { const isActive = currentRoomId === room.id; const safeTitle = room.title.replace(/'/g, "\\'"); return `
${room.title} ${room.time}
${room.type} ${room.unread > 0 ? `${room.unread}` : ''}
`; }).join(''); } // انتخاب یک چت window.selectRoom = function (id, title) { currentRoomId = id; lastMessageId = 0; isFetchingMessages = false; // ریست کردن قفل UI.noChatSelected.classList.add('hidden'); UI.chatHeader.classList.remove('invisible'); UI.messages.classList.remove('invisible'); UI.inputArea.classList.remove('invisible'); UI.chatTitle.textContent = title; UI.messages.innerHTML = '
autorenew
'; fetchRooms(); stopPolling(); fetchMessages().then(() => { startPolling(); scrollToBottom(); }); UI.input.focus(); }; // گرفتن پیام‌ها از سرور async function fetchMessages() { // 🟢 اگر هیچ رومی انتخاب نشده، یا درخواست قبلی هنوز تمام نشده، برگرد! if (!currentRoomId || isFetchingMessages) return; isFetchingMessages = true; // 🟢 فعال کردن قفل try { UI.indicator.classList.remove('hidden'); setTimeout(() => UI.indicator.classList.add('hidden'), 500); const res = await fetch(`${window.CHAT_CONFIG.apiUrlMessagesBase}${currentRoomId}/?last_id=${lastMessageId}`); const data = await res.json(); if (data.messages && data.messages.length > 0) { if (lastMessageId === 0) UI.messages.innerHTML = ''; renderMessages(data.messages); lastMessageId = data.messages[data.messages.length - 1].id; scrollToBottom(); } else if (lastMessageId === 0) { UI.messages.innerHTML = `
forum

No messages yet. Say hi!

`; } } catch (e) { console.error("Failed to fetch messages:", e); } finally { isFetchingMessages = false; // 🟢 باز کردن قفل در هر شرایطی (چه موفق چه ارور) } } // رندر کردن حباب‌های پیام function renderMessages(messages) { const html = messages.map(m => { const isMe = m.is_me; const alignClass = isMe ? 'message-sent' : 'message-received'; const bubbleClass = isMe ? 'message-bubble-sent' : 'message-bubble-received'; const senderName = !isMe ? `
${m.sender_name}
` : ''; const safeContent = m.content.replace(//g, ">"); const timeColor = isMe ? 'text-blue-100' : 'text-gray-400'; const tickIcon = isMe ? `done_all` : ''; return `
${senderName}

${safeContent}

${m.sent_at} ${tickIcon}
`; }).join(''); UI.messages.insertAdjacentHTML('beforeend', html); } // اسکرول به پایین function scrollToBottom() { UI.messages.scrollTo({ top: UI.messages.scrollHeight, behavior: 'smooth' }); } // ارسال پیام جدید UI.form.addEventListener('submit', async (e) => { e.preventDefault(); const text = UI.input.value.trim(); if (!text || !currentRoomId) return; UI.input.value = ''; try { await fetch(`${window.CHAT_CONFIG.apiUrlSendBase}${currentRoomId}/`, { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRFToken': window.CHAT_CONFIG.csrfToken }, body: JSON.stringify({ content: text }) }); // 🟢 صدا زدن دریافت پیام به صورت ایمن await fetchMessages(); fetchRooms(); } catch (e) { console.error("Failed to send message:", e); } }); // راه‌اندازی Polling function startPolling() { messagePollInterval = setInterval(fetchMessages, 3000); } function stopPolling() { if (messagePollInterval) clearInterval(messagePollInterval); } // مقداردهی اولیه fetchRooms(); roomPollInterval = setInterval(fetchRooms, 10000); });