(function () {
function escapeHtml(value) {
return String(value || '')
.replace(/&/g, '&')
.replace(//g, '>')
.replace(/\"/g, '"')
.replace(/'/g, ''');
}
function renderMessage(message, currentUserId) {
var ownClass = Number(message.user_id) === Number(currentUserId) ? ' kgvvm-chat-message--own' : '';
var roleLabel = message.role ? ' · ' + escapeHtml(message.role) : '';
var text = escapeHtml(message.message).replace(/\n/g, '
');
return '' +
'';
}
document.addEventListener('DOMContentLoaded', function () {
var app = document.querySelector('.kgvvm-chat-app');
if (!app || typeof window.kgvvmChatConfig === 'undefined') {
return;
}
var config = window.kgvvmChatConfig;
var messagesEl = app.querySelector('[data-chat-messages]');
var form = app.querySelector('[data-chat-form]');
var input = app.querySelector('[data-chat-input]');
var status = app.querySelector('[data-chat-status]');
var roomButtons = app.querySelectorAll('[data-chat-room]');
var roomTitle = app.querySelector('[data-chat-room-title]');
var roomDescription = app.querySelector('[data-chat-room-description]');
var currentRoom = app.getAttribute('data-room') || 'general';
var initialRoom = currentRoom;
var currentUserId = Number(app.getAttribute('data-current-user-id') || '0');
var sendLocked = false;
var storageKey = 'kgvvmActiveChatRoom';
function getAvailableRooms() {
return Array.prototype.map.call(roomButtons, function (button) {
return button.getAttribute('data-chat-room') || '';
}).filter(Boolean);
}
function syncRoomState() {
try {
window.localStorage.setItem(storageKey, currentRoom);
} catch (error) {
// ignore storage errors
}
if (window.history && typeof window.history.replaceState === 'function') {
var url = new window.URL(window.location.href);
url.searchParams.set('room', currentRoom);
window.history.replaceState({}, '', url.toString());
}
}
function restoreRoomState() {
var availableRooms = getAvailableRooms();
var url = new window.URL(window.location.href);
var requestedRoom = url.searchParams.get('room') || '';
var storedRoom = '';
try {
storedRoom = window.localStorage.getItem(storageKey) || '';
} catch (error) {
storedRoom = '';
}
var preferredRoom = requestedRoom || storedRoom;
if (preferredRoom && availableRooms.indexOf(preferredRoom) !== -1) {
currentRoom = preferredRoom;
app.setAttribute('data-room', currentRoom);
}
}
function setStatus(text, isError) {
if (!status) {
return;
}
status.textContent = text || '';
status.classList.toggle('is-error', !!isError);
}
function scrollToBottom() {
if (messagesEl) {
messagesEl.scrollTop = messagesEl.scrollHeight;
}
}
function updateRoomButtons() {
roomButtons.forEach(function (button) {
button.classList.toggle('is-active', button.getAttribute('data-chat-room') === currentRoom);
});
}
function updateRoomMeta() {
roomButtons.forEach(function (button) {
if (button.getAttribute('data-chat-room') !== currentRoom) {
return;
}
if (roomTitle) {
roomTitle.textContent = button.getAttribute('data-chat-label') || '';
}
if (roomDescription) {
roomDescription.textContent = button.getAttribute('data-chat-description') || '';
}
});
}
function renderMessages(messages, replaceAll) {
if (!messagesEl) {
return;
}
if (replaceAll) {
messagesEl.innerHTML = '';
}
if (!Array.isArray(messages) || !messages.length) {
if (replaceAll) {
messagesEl.innerHTML = '
' + escapeHtml(config.i18n.empty) + '
'; messagesEl.dataset.lastId = '0'; } return; } if (messagesEl.querySelector('.kgvvm-chat-empty')) { messagesEl.innerHTML = ''; } messages.forEach(function (message) { messagesEl.insertAdjacentHTML('beforeend', renderMessage(message, currentUserId)); messagesEl.dataset.lastId = String(message.id || messagesEl.dataset.lastId || '0'); }); scrollToBottom(); } function fetchMessages(replaceAll) { var data = new window.FormData(); data.append('action', 'kgvvm_fetch_chat_messages'); data.append('nonce', config.nonce); data.append('room', currentRoom); if (!replaceAll && messagesEl && messagesEl.dataset.lastId) { data.append('after_id', messagesEl.dataset.lastId); } return window.fetch(config.ajaxUrl, { method: 'POST', credentials: 'same-origin', body: data }) .then(function (response) { return response.json(); }) .then(function (payload) { if (!payload || !payload.success) { return; } renderMessages(payload.data.messages || [], replaceAll); }) .catch(function () { setStatus(config.i18n.fetchError, true); }); } roomButtons.forEach(function (button) { button.addEventListener('click', function () { currentRoom = button.getAttribute('data-chat-room') || 'general'; app.setAttribute('data-room', currentRoom); syncRoomState(); updateRoomMeta(); if (messagesEl) { messagesEl.dataset.lastId = '0'; } updateRoomButtons(); setStatus(config.i18n.loading, false); fetchMessages(true).then(function () { setStatus('', false); }); }); }); if (form && input) { form.addEventListener('submit', function (event) { event.preventDefault(); if (sendLocked) { return; } var message = String(input.value || '').trim(); if (!message) { return; } sendLocked = true; setStatus(config.i18n.sending, false); var data = new window.FormData(); data.append('action', 'kgvvm_send_chat_message'); data.append('nonce', config.nonce); data.append('room', currentRoom); data.append('message', message); window.fetch(config.ajaxUrl, { method: 'POST', credentials: 'same-origin', body: data }) .then(function (response) { return response.json(); }) .then(function (payload) { sendLocked = false; if (!payload || !payload.success) { setStatus(config.i18n.sendError, true); return; } renderMessages(payload.data.messages || [], false); input.value = ''; input.focus(); setStatus('', false); }) .catch(function () { sendLocked = false; setStatus(config.i18n.sendError, true); }); }); } restoreRoomState(); updateRoomButtons(); updateRoomMeta(); syncRoomState(); if (currentRoom !== initialRoom) { fetchMessages(true); } scrollToBottom(); window.setInterval(function () { fetchMessages(false); }, Number(config.refreshInterval || 7000)); }); })();