|
|
@ -155,7 +155,7 @@ document.addEventListener('DOMContentLoaded', function () { |
|
|
</div> |
|
|
</div> |
|
|
<div class="flex justify-between items-center"> |
|
|
<div class="flex justify-between items-center"> |
|
|
<span class="text-[12px] font-medium text-gray-500 truncate">${room.type === 'group' ? '👥 Group Chat' : '👤 Private Chat'}</span> |
|
|
<span class="text-[12px] font-medium text-gray-500 truncate">${room.type === 'group' ? '👥 Group Chat' : '👤 Private Chat'}</span> |
|
|
${room.unread > 0 ? `<span class="bg-blue-500 shadow-sm text-white text-[10px] font-bold px-2 py-0.5 rounded-full">${room.unread}</span>` : ''} |
|
|
|
|
|
|
|
|
${room.unread > 0 ? `<span class="shadow-sm text-[10px] font-bold rounded-full unread-badge">${room.unread}</span>` : ''} |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
</div> |
|
|
@ -168,6 +168,15 @@ document.addEventListener('DOMContentLoaded', function () { |
|
|
lastMessageId = 0; |
|
|
lastMessageId = 0; |
|
|
isFetchingMessages = false; |
|
|
isFetchingMessages = false; |
|
|
|
|
|
|
|
|
|
|
|
// 🟢 Optimistic UI: Update active state and remove unread badge immediately
|
|
|
|
|
|
document.querySelectorAll('.room-item').forEach(el => el.classList.remove('room-item-active')); |
|
|
|
|
|
const clickedRoom = document.querySelector(`.room-item[onclick*="selectRoom(${id}"]`); |
|
|
|
|
|
if (clickedRoom) { |
|
|
|
|
|
clickedRoom.classList.add('room-item-active'); |
|
|
|
|
|
const badge = clickedRoom.querySelector('.unread-badge'); |
|
|
|
|
|
if (badge) badge.remove(); // Hide badge instantly
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
// 🟢 تغییر invisible به hidden برای کارکرد درست بلوکها
|
|
|
// 🟢 تغییر invisible به hidden برای کارکرد درست بلوکها
|
|
|
UI.noChatSelected.classList.add('hidden'); |
|
|
UI.noChatSelected.classList.add('hidden'); |
|
|
UI.chatHeaderInfo.classList.remove('hidden'); // 🟢 تغییر یافته
|
|
|
UI.chatHeaderInfo.classList.remove('hidden'); // 🟢 تغییر یافته
|
|
|
@ -177,12 +186,11 @@ document.addEventListener('DOMContentLoaded', function () { |
|
|
UI.chatTitle.textContent = title; |
|
|
UI.chatTitle.textContent = title; |
|
|
UI.messages.innerHTML = '<div class="flex items-center justify-center h-full"><span class="material-symbols-outlined animate-spin text-gray-400 text-3xl">autorenew</span></div>'; |
|
|
UI.messages.innerHTML = '<div class="flex items-center justify-center h-full"><span class="material-symbols-outlined animate-spin text-gray-400 text-3xl">autorenew</span></div>'; |
|
|
|
|
|
|
|
|
fetchRooms(); |
|
|
|
|
|
|
|
|
|
|
|
stopPolling(); |
|
|
stopPolling(); |
|
|
fetchMessages().then(() => { |
|
|
fetchMessages().then(() => { |
|
|
startPolling(); |
|
|
startPolling(); |
|
|
scrollToBottom(); |
|
|
scrollToBottom(); |
|
|
|
|
|
fetchRooms(); // Sync with backend to ensure exact unread counts
|
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
UI.input.focus(); |
|
|
UI.input.focus(); |
|
|
@ -249,12 +257,12 @@ document.addEventListener('DOMContentLoaded', function () { |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
// ── Textarea Auto-resize & Key Handling ──
|
|
|
// ── Textarea Auto-resize & Key Handling ──
|
|
|
UI.input.addEventListener('input', function() { |
|
|
|
|
|
|
|
|
UI.input.addEventListener('input', function () { |
|
|
this.style.height = 'auto'; |
|
|
this.style.height = 'auto'; |
|
|
this.style.height = (this.scrollHeight) + 'px'; |
|
|
this.style.height = (this.scrollHeight) + 'px'; |
|
|
}); |
|
|
}); |
|
|
|
|
|
|
|
|
UI.input.addEventListener('keydown', function(e) { |
|
|
|
|
|
|
|
|
UI.input.addEventListener('keydown', function (e) { |
|
|
if (e.key === 'Enter' && !e.shiftKey) { |
|
|
if (e.key === 'Enter' && !e.shiftKey) { |
|
|
e.preventDefault(); |
|
|
e.preventDefault(); |
|
|
// Trigger form submit
|
|
|
// Trigger form submit
|
|
|
|