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);
});