TKK_E32230273/test.js

782 lines
29 KiB
JavaScript

let contacts = [];
let activeOccupantId = null;
let activeAvatarUrl = '';
function formatTime(dateStr) {
if(!dateStr) return '';
const date = new Date(dateStr);
let hours = date.getHours();
let minutes = date.getMinutes();
const ampm = hours >= 12 ? 'PM' : 'AM';
hours = hours % 12;
hours = hours ? hours : 12;
minutes = minutes < 10 ? '0'+minutes : minutes;
return hours + ':' + minutes + ' ' + ampm;
}
function formatRelative(dateStr) {
if(!dateStr) return '';
const date = new Date(dateStr);
const now = new Date();
const diffMs = now - date;
const diffMins = Math.floor(diffMs / 60000);
if(diffMins < 60) return diffMins + ' Min';
const diffHours = Math.floor(diffMins / 60);
if(diffHours < 24) return diffHours + ' Hour';
const diffDays = Math.floor(diffHours / 24);
return diffDays + ' Day';
}
function loadContacts() {
$.post('chat_api.php', { action: 'get_contacts' }, function(res) {
if(res.status === 'success') {
contacts = res.data;
renderContacts(contacts);
}
}, 'json');
}
function renderContacts(data) {
let chatsHtml = '';
let contactsHtml = '';
const nowServer = new Date();
data.forEach(c => {
let activeClass = (c.id_occupant == activeOccupantId) ? 'active' : '';
// Cek jika pesan berisi media sebelumnya dicadangkan sbg teks dummy
let rawLastMsg = c.last_message || '';
let strippedMsg = rawLastMsg.replace(/<[^>]*>?/gm, '').trim();
if(!strippedMsg && rawLastMsg.includes('<img')) strippedMsg = '📷 Foto';
if(!strippedMsg && rawLastMsg.includes('mdi-file-document')) strippedMsg = '📄 Dokumen';
if(!strippedMsg && rawLastMsg.includes('<video')) strippedMsg = '🎥 Video';
if(!strippedMsg && rawLastMsg.includes('<audio')) strippedMsg = '🎵 Audio';
let lastMsg = strippedMsg || (rawLastMsg ? 'Lampiran' : 'Start a conversation');
let timeStr = c.last_time ? formatRelative(c.last_time) : '';
let isOnline = false;
if (c.last_active) {
let lastActStr = c.last_active.replace(/-/g, '/');
let actDate = new Date(lastActStr);
let diffSec = (nowServer - actDate) / 1000;
if (diffSec < 20) {
isOnline = true;
}
}
let statusColor = isOnline ? '#10b981' : '#f59e0b';
let unreadBadge = '';
let nameStyle = 'font-weight: 600;';
let msgStyle = '';
if (c.unread_count > 0 && c.id_occupant != activeOccupantId) {
unreadBadge = `<span class="ci-unread-badge">${c.unread_count}</span>`;
nameStyle = 'font-weight: 800; color: #000;';
msgStyle = 'font-weight: 700; color: #222;';
}
let html = `
<div class="contact-item ${activeClass}" onclick="openChat(${c.id_occupant})">
<div class="ci-avatar">
<img src="${c.foto}" alt="${c.name}">
<div class="ci-status" style="background:${statusColor}"></div>
</div>
<div class="ci-info">
<div class="ci-header">
<div class="ci-name" style="${nameStyle}">${c.name}${unreadBadge}</div>
<div class="ci-time">${timeStr}</div>
</div>
<div class="ci-msg" style="${msgStyle}">${lastMsg}</div>
</div>
</div>
`;
if(c.last_time) {
chatsHtml += html;
} else {
contactsHtml += html;
}
});
if(chatsHtml) {
document.getElementById('chatsList').innerHTML = chatsHtml;
document.getElementById('chatsSection').style.display = 'block';
} else {
document.getElementById('chatsSection').style.display = 'none';
}
if(contactsHtml) {
document.getElementById('contactsList').innerHTML = contactsHtml;
document.getElementById('contactsSection').style.display = 'block';
} else {
document.getElementById('contactsSection').style.display = 'none';
}
}
function filterContacts() {
let q = document.getElementById('searchInput').value.toLowerCase();
let filtered = contacts.filter(c => c.name.toLowerCase().includes(q));
renderContacts(filtered);
}
function openChat(id) {
activeOccupantId = id;
renderContacts(contacts);
document.getElementById('chatBlank').style.display = 'none';
document.getElementById('chatActive').style.display = 'flex';
document.getElementById('chatHistory').innerHTML = '<div style="text-align:center; padding:20px; color:#999;">Loading...</div>';
$.post('chat_api.php', { action: 'get_messages', id_occupant: id }, function(res) {
if(res.status === 'success') {
document.getElementById('activeName').innerText = res.occupant.name;
let occStatStr = 'Status tidak diketahui';
if (res.occupant.last_active) {
let lastActStr = res.occupant.last_active.replace(/-/g, '/');
let actDate = new Date(lastActStr);
let diffSec = (new Date() - actDate) / 1000;
let diffDays = diffSec / (60 * 60 * 24);
if (diffSec < 20) {
occStatStr = 'Online';
} else if (diffDays > 7) {
let jam = actDate.getHours().toString().padStart(2, '0');
let menit = actDate.getMinutes().toString().padStart(2, '0');
let tgl = actDate.getDate().toString().padStart(2, '0');
let bln = (actDate.getMonth() + 1).toString().padStart(2, '0');
let thn = actDate.getFullYear();
occStatStr = `Terakhir Online ${jam}.${menit} ${tgl}-${bln}-${thn}`;
} else {
const hariArr = ['Minggu', 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu'];
let namaHari = hariArr[actDate.getDay()];
let jam = actDate.getHours().toString().padStart(2, '0');
let menit = actDate.getMinutes().toString().padStart(2, '0');
occStatStr = `Terakhir Online Jam ${jam}:${menit} Hari ${namaHari}`;
}
}
document.getElementById('activeStatus').innerText = occStatStr;
document.getElementById('activeAvatar').src = res.occupant.foto;
activeAvatarUrl = res.occupant.foto;
renderMessages(res.data);
loadContacts();
}
}, 'json');
}
function buildMessagesHtml(messages) {
let html = '';
const adminAvatar = 'images/admin.png';
messages.forEach(msg => {
let isRight = (msg.sender === 'account');
let cls = isRight ? 'msg-right' : 'msg-left';
let statusHtml = '';
if (isRight) {
if (msg.is_read == 1) {
statusHtml = '<span class="msg-status msg-status-read"><i class="mdi mdi-check-all"></i></span>';
} else if (msg.telegram_msg_id) {
statusHtml = '<span class="msg-status msg-status-delivered"><i class="mdi mdi-check-all"></i></span>';
} else {
statusHtml = '<span class="msg-status msg-status-sent"><i class="mdi mdi-check"></i></span>';
}
}
let avatarToUse = isRight ? adminAvatar : activeAvatarUrl;
let onContextMenu = `oncontextmenu="showContextMenu(event, ${msg.id_chat}, '${msg.sender}', this); return false;"`;
let replyBlock = '';
if (msg.reply_to_chat_id && msg.reply_message) {
let rpSender = (msg.reply_sender === 'account') ? 'Anda' : document.getElementById('activeName').innerText;
let strippedRpMsg = msg.reply_message.replace(/<[^>]*>?/gm, '');
if(!strippedRpMsg) strippedRpMsg = 'Lampiran/File';
replyBlock = `<div class="msg-reply-block" onclick="scrollToMsg(${msg.reply_to_chat_id})">` +
`<div class="replier">${rpSender}</div>` +
`<div style="white-space:nowrap; overflow:hidden; text-overflow:ellipsis; max-width:200px;">${strippedRpMsg}</div>` +
`</div>`;
}
let msgOutput = msg.message;
let timeOutput = `<div class="msg-time">${formatTime(msg.created_at)} ${statusHtml}</div>`;
let bubbleClass = 'msg-bubble';
// Additional Logic for Selection Mode
let selectionClasses = '';
if (isSelectionMode) {
selectionClasses = 'selectable';
if (selectedMessages.some(sm => sm.id === msg.id_chat)) selectionClasses += ' selected';
}
let checkboxHtml = `<div class="msg-checkbox" onclick="toggleSelectMessage(event, ${msg.id_chat}, '${msg.sender}')"><i class="mdi mdi-checkbox-blank-circle-outline"></i></div>`;
let msgRowClick = isSelectionMode ? `onclick="toggleSelectMessage(event, ${msg.id_chat}, '${msg.sender}')"` : '';
html += `
<div class="msg-row ${cls} ${selectionClasses}" id="msg-${msg.id_chat}" data-id="${msg.id_chat}" ${msgRowClick}>
${checkboxHtml}
<img src="${avatarToUse}">
<div class="msg-content">
<div class="${bubbleClass}" ${onContextMenu}>${replyBlock}${msgOutput}</div>
${timeOutput}
</div>
</div>
`;
});
return html;
}
function renderMessages(messages) {
let hist = document.getElementById('chatHistory');
let newHtml = buildMessagesHtml(messages);
if (hist.innerHTML !== newHtml) {
let isScrolledBottom = hist.scrollHeight - hist.clientHeight <= hist.scrollTop + 10;
hist.innerHTML = newHtml;
if (isScrolledBottom || hist.scrollTop === 0) {
scrollToBottom();
}
}
}
function scrollToBottom() {
let hist = document.getElementById('chatHistory');
hist.scrollTop = hist.scrollHeight;
}
function scrollToMsg(id) {
let el = document.getElementById('msg-' + id);
if(el) {
el.scrollIntoView({behavior: "smooth", block: "center"});
el.style.backgroundColor = 'rgba(88, 86, 214, 0.2)';
setTimeout(() => { el.style.backgroundColor = 'transparent'; }, 1000);
}
}
function handleEnter(e) {
if(e.key === 'Enter' && !e.shiftKey) {
e.preventDefault(); // Mencegah pindah baris
submitMessageOrEdit();
}
}
// Auto-resize textarea
document.addEventListener('input', function (e) {
if (e.target.id === 'messageInput') {
e.target.style.height = 'auto'; // Reset height
e.target.style.height = (e.target.scrollHeight) + 'px'; // Set to scroll height
}
});
function submitMessageOrEdit() {
if (editingMsgId) {
saveEdit();
} else {
sendMessage();
}
}
function sendMessage() {
let input = document.getElementById('messageInput');
let text = input.value.trim();
if(!text || !activeOccupantId) return;
let formData = new FormData();
formData.append('action', 'send_message');
formData.append('id_occupant', activeOccupantId);
formData.append('message', text);
formData.append('sender', 'account');
if (replyingToId) formData.append('reply_to_chat_id', replyingToId);
let tempId = 'temp-' + Date.now();
let optStatus = '<span class="msg-status msg-status-sending"><i class="mdi mdi-clock-outline"></i></span>';
let timeOutput = `<div class="msg-time">Mengirim... ${optStatus}</div>`;
let hist = document.getElementById('chatHistory');
let tempRow = document.createElement('div');
tempRow.className = 'msg-row msg-right msg-sending';
tempRow.id = tempId;
let escapedText = text.replace(/</g, '&lt;').replace(/>/g, '&gt;');
tempRow.innerHTML = `
<img src="images/admin.png">
<div class="msg-content">
<div class="msg-bubble">${escapedText}</div>
${timeOutput}
</div>
`;
hist.appendChild(tempRow);
scrollToBottom();
input.value = '';
input.style.height = 'auto'; // Reset textarea height
closeReplyBox();
$.ajax({
url: 'chat_api.php',
type: 'POST',
data: formData,
contentType: false,
processData: false,
dataType: 'json',
success: function(res) {
if(res.status === 'success') {
loadContacts();
$.post('chat_api.php', { action: 'get_messages', id_occupant: activeOccupantId }, function(res2) {
if(res2.status === 'success') {
renderMessages(res2.data);
}
}, 'json');
} else {
let el = document.getElementById(tempId);
if (el) {
el.querySelector('.msg-status').innerHTML = '<i class="mdi mdi-alert-circle" style="color:#ef4444;font-size:14px;" title="Gagal terkirim"></i>';
el.classList.remove('msg-sending');
}
}
},
error: function() {
let el = document.getElementById(tempId);
if (el) {
el.querySelector('.msg-status').innerHTML = '<i class="mdi mdi-alert-circle" style="color:#ef4444;font-size:14px;" title="Gagal terkirim"></i>';
el.classList.remove('msg-sending');
}
}
});
}
// ═══ EMOJI PICKER ═══
const emojiData = {
smileys: ['😀','😃','😄','😁','😆','😅','🤣','😂','🙂','😊','😇','🥰','😍','🤩','😘','😋','😛','😜','🤪','😝','🤑','🤗','🤭','🤫','🤔','🤐','🤨','😐','😑','😶','😏','😒','🙄','😬','😮‍💨','🤥','😌','😔','😪','🤤','😴','😷','🤒','🤕','🤢','🤮','🥵','🥶','😵','🤯','🥳','🥸','😎','🤓','🧐'],
gestures: ['👍','👎','👌','🤌','🤏','✌️','🤞','🤟','🤘','🤙','👈','👉','👆','👇','☝️','✋','🤚','🖐️','🖖','👋','🤝','👏','✍️','🙏','💪','🦾','🫶','🫱','🫲'],
hearts: ['❤️','🧡','💛','💚','💙','💜','🖤','🤍','🤎','💔','❤️‍🔥','❤️‍🩹','💕','💞','💓','💗','💖','💘','💝','💟','♥️','🫀'],
objects: ['🎉','🎊','🎈','🎁','🎀','🏆','🥇','🎵','🎶','🎸','🎹','🎤','🔔','⭐','🌟','💫','✨','⚡','🔥','💥','🎯','💡','📌','📎','✅','❌','⚠️','💬','💭','🗨️'],
animals: ['🐶','🐱','🐭','🐹','🐰','🦊','🐻','🐼','🐨','🐯','🦁','🐮','🐷','🐸','🐵','🐔','🐧','🐦','🦅','🦉','🐴','🦄','🐝','🐛','🦋','🐌','🐞','🐙','🐠','🐳'],
food: ['🍕','🍔','🍟','🌭','🍿','🧀','🥚','🍳','🥞','🧇','🥓','🥩','🍗','🍖','🌮','🌯','🥗','🍜','🍝','🍣','🍤','🍩','🍪','🎂','🍰','🧁','🍫','🍬','🍭','☕','🍵','🥤','🧃','🍷','🍺']
};
function toggleEmoji() {
let picker = document.getElementById('emojiPicker');
picker.classList.toggle('show');
if (picker.classList.contains('show')) renderEmojis('smileys');
}
function renderEmojis(cat) {
let grid = document.getElementById('emojiGrid');
grid.innerHTML = emojiData[cat].map(e => `<div class="emoji-item" onclick="insertEmoji('${e}')">${e}</div>`).join('');
}
function insertEmoji(e) {
let input = document.getElementById('messageInput');
input.value += e;
input.style.height = 'auto';
input.style.height = (input.scrollHeight) + 'px';
input.focus();
}
document.addEventListener('click', function(e) {
if(e.target.classList.contains('emoji-tab')) {
document.querySelectorAll('.emoji-tab').forEach(t => t.classList.remove('active'));
e.target.classList.add('active');
renderEmojis(e.target.dataset.cat);
}
let picker = document.getElementById('emojiPicker');
let btn = document.getElementById('btnEmoji');
if (picker && btn && picker.classList.contains('show') && !picker.contains(e.target) && !btn.contains(e.target)) {
picker.classList.remove('show');
}
});
// Context Menu Logic
let selectedMsgId = null;
let selectedMsgSender = null;
let selectedMsgText = null;
let replyingToId = null;
let editingMsgId = null;
let originalEditMsgText = null;
// Selection Mode State
let isSelectionMode = false;
let selectedMessages = []; // Array of objects: {id, sender}
function showContextMenu(e, idChat, sender, bubbleEl) {
e.preventDefault();
selectedMsgId = idChat;
selectedMsgSender = sender;
// Extract text ignoring the reply block and the (Diedit) tag
let clone = bubbleEl.cloneNode(true);
let replyBlocks = clone.querySelectorAll('.msg-reply-block');
replyBlocks.forEach(b => b.remove());
let editTags = clone.querySelectorAll('i'); // Removes the (Diedit) tag along with other icons
editTags.forEach(t => t.remove());
selectedMsgText = (clone.textContent || '').trim();
let menu = document.getElementById('msgContextMenu');
// Show/hide Edit button based on sender
let btnEdit = document.getElementById('ctxMenuEdit');
if (sender === 'account') {
btnEdit.style.display = 'flex';
} else {
btnEdit.style.display = 'none';
}
let x = e.clientX;
let y = e.clientY;
if (x + 180 > window.innerWidth) x = window.innerWidth - 190;
if (y + 130 > window.innerHeight) y = window.innerHeight - 130;
menu.style.left = x + 'px';
menu.style.top = y + 'px';
menu.style.display = 'block';
}
function prepareReply(event) {
if(event) event.stopPropagation();
replyingToId = selectedMsgId;
let title = (selectedMsgSender === 'account') ? 'Membalas Anda' : ('Membalas ' + document.getElementById('activeName').innerText);
document.getElementById('rpTitle').innerText = title;
document.getElementById('rpText').innerText = selectedMsgText;
document.getElementById('replyPreview').style.display = 'block';
document.getElementById('messageInput').focus();
hideContextMenu();
}
function closeReplyBox() {
replyingToId = null;
document.getElementById('replyPreview').style.display = 'none';
}
function hideContextMenu() {
document.getElementById('msgContextMenu').style.display = 'none';
}
document.addEventListener('click', function(e) {
hideContextMenu();
});
function deleteSelectedMessage(event) {
if(event) event.stopPropagation();
hideContextMenu();
if (!selectedMsgId) return;
let msgElement = document.getElementById('msg-' + selectedMsgId);
if (selectedMsgSender === 'account') {
// Pesan Admin: Ada pilihan Hapus untuk Semua atau Hanya Saya
Swal.fire({
title: 'Hapus Pesan?',
text: "Pilih metode penghapusan.",
icon: 'warning',
showDenyButton: true,
showCancelButton: true,
confirmButtonText: 'Hapus utk Semua',
denyButtonText: 'Hapus utk Saya',
cancelButtonText: 'Batal',
customClass: {
popup: 'swal2-custom-small',
confirmButton: 'swal-btn-delete-all',
denyButton: 'swal-btn-delete-me',
cancelButton: 'swal-btn-cancel'
},
buttonsStyling: false
}).then((result) => {
if (result.isConfirmed) {
// Semua
executeDelete(selectedMsgId, msgElement, 'everyone');
} else if (result.isDenied) {
// Saya
executeDelete(selectedMsgId, msgElement, 'me');
}
});
} else {
// Pesan Occupant: Hanya bisa Hapus untuk Saya
Swal.fire({
title: 'Hapus Pesan?',
text: "Pesan ini hanya terhapus pada layar Anda.",
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Hapus utk Saya',
cancelButtonText: 'Batal',
customClass: {
popup: 'swal2-custom-small',
confirmButton: 'swal-btn-delete-me',
cancelButton: 'swal-btn-cancel'
},
buttonsStyling: false
}).then((result) => {
if (result.isConfirmed) {
executeDelete(selectedMsgId, msgElement, 'me');
}
});
}
}
function executeDelete(id, msgElement, type) {
if (msgElement) msgElement.style.opacity = '0.5';
$.post('chat_api.php', { action: 'delete_message', id_chat: id, delete_type: type }, function(res) {
if(res.status === 'success') {
$('#msg-' + id).fadeOut(300, function() { $(this).remove(); });
} else {
if (msgElement) msgElement.style.opacity = '1';
Swal.fire('Gagal', res.message || 'Pesan tidak dapat dihapus', 'error');
}
}, 'json');
}
// ========================
// BULK DELETE & SELECTION
// ========================
function enterSelectionMode(event) {
if(event) event.stopPropagation();
hideContextMenu();
isSelectionMode = true;
selectedMessages = [{ id: selectedMsgId, sender: selectedMsgSender }];
// Stop editing/replying if active
cancelEdit();
closeReplyBox();
// Switch header actions
document.getElementById('normalHeaderActions').style.display = 'none';
document.getElementById('selectionHeaderActions').style.display = 'flex';
document.getElementById('selectionCount').innerText = selectedMessages.length;
// Add selectable classes to all rows and selected to the first one
let rows = document.querySelectorAll('.msg-row');
rows.forEach(row => {
row.classList.add('selectable');
// Add onclick to rows that are currently loaded
row.setAttribute('onclick', `toggleSelectMessage(event, ${row.getAttribute('data-id')}, '${row.classList.contains('msg-right') ? 'account' : 'occupant'}')`);
});
document.getElementById('msg-' + selectedMsgId).classList.add('selected');
}
function exitSelectionMode() {
isSelectionMode = false;
selectedMessages = [];
// Switch header actions back
document.getElementById('normalHeaderActions').style.display = 'block';
document.getElementById('selectionHeaderActions').style.display = 'none';
// Remove selectable classes
let rows = document.querySelectorAll('.msg-row');
rows.forEach(row => {
row.classList.remove('selectable', 'selected');
row.removeAttribute('onclick'); // Important: remove the bulk select onclick
});
}
function toggleSelectMessage(event, idChat, sender) {
if(event) event.stopPropagation();
if(!isSelectionMode) return;
let index = selectedMessages.findIndex(m => m.id === idChat);
let row = document.getElementById('msg-' + idChat);
if (index > -1) {
// Deselect
selectedMessages.splice(index, 1);
if(row) row.classList.remove('selected');
} else {
// Select
selectedMessages.push({ id: idChat, sender: sender });
if(row) row.classList.add('selected');
}
document.getElementById('selectionCount').innerText = selectedMessages.length;
// If no messages selected, automatically exit selection mode
if (selectedMessages.length === 0) {
exitSelectionMode();
}
}
function triggerBulkDelete() {
if (selectedMessages.length === 0) return;
// Check if ALL selected messages are from admin
let onlyAdminMessages = selectedMessages.every(m => m.sender === 'account');
if (onlyAdminMessages) {
// Admin only: Can choose 'Untuk Semua' or 'Hanya Saya'
Swal.fire({
title: 'Hapus ' + selectedMessages.length + ' Pesan?',
text: "Pilih metode penghapusan.",
icon: 'warning',
showDenyButton: true,
showCancelButton: true,
confirmButtonText: 'Hapus utk Semua',
denyButtonText: 'Hapus utk Saya',
cancelButtonText: 'Batal',
customClass: {
popup: 'swal2-custom-small',
confirmButton: 'swal-btn-delete-all',
denyButton: 'swal-btn-delete-me',
cancelButton: 'swal-btn-cancel'
},
buttonsStyling: false
}).then((result) => {
if (result.isConfirmed) {
executeBulkDelete('everyone');
} else if (result.isDenied) {
executeBulkDelete('me');
}
});
} else {
// Mix of Admin + Occupant OR Occupant only: Only 'Hanya Saya'
Swal.fire({
title: 'Hapus ' + selectedMessages.length + ' Pesan?',
text: "Pesan-pesan ini hanya terhapus pada layar Anda.",
icon: 'warning',
showCancelButton: true,
confirmButtonText: 'Hapus',
cancelButtonText: 'Batal',
customClass: {
popup: 'swal2-custom-small',
confirmButton: 'swal-btn-delete-me',
cancelButton: 'swal-btn-cancel'
},
buttonsStyling: false
}).then((result) => {
if (result.isConfirmed) {
executeBulkDelete('me');
}
});
}
}
function executeBulkDelete(type) {
let idsToDelete = selectedMessages.map(m => m.id);
// Dim the UI immediately
idsToDelete.forEach(id => {
let el = document.getElementById('msg-' + id);
if(el) el.style.opacity = '0.5';
});
$.post('chat_api.php', {
action: 'bulk_delete_messages',
id_chats: idsToDelete,
delete_type: type
}, function(res) {
if(res.status === 'success') {
idsToDelete.forEach(id => {
$('#msg-' + id).fadeOut(300, function() { $(this).remove(); });
});
exitSelectionMode();
Swal.fire({
title: 'Terhapus!',
text: res.message,
icon: 'success',
timer: 1500,
showConfirmButton: false
});
} else {
// Revert opacity
idsToDelete.forEach(id => {
let el = document.getElementById('msg-' + id);
if(el) el.style.opacity = '1';
});
Swal.fire('Gagal', res.message || 'Gagal menghapus beberapa pesan', 'error');
}
}, 'json');
}
function editSelectedMessage(event) {
if(event) event.stopPropagation();
hideContextMenu();
if (!selectedMsgId || selectedMsgSender !== 'account') return;
editingMsgId = selectedMsgId;
originalEditMsgText = selectedMsgText;
// Set UI to Edit Mode
document.getElementById('epText').innerText = originalEditMsgText;
document.getElementById('editPreview').style.display = 'block';
// If user was replying, cancel it so they don't do both
closeReplyBox();
let inputEl = document.getElementById('messageInput');
inputEl.value = originalEditMsgText;
inputEl.style.height = 'auto';
inputEl.style.height = (inputEl.scrollHeight) + 'px';
inputEl.focus();
}
function cancelEdit() {
editingMsgId = null;
originalEditMsgText = null;
document.getElementById('editPreview').style.display = 'none';
let inputEl = document.getElementById('messageInput');
inputEl.value = '';
inputEl.style.height = 'auto';
}
function saveEdit() {
let input = document.getElementById('messageInput');
let newText = input.value.trim();
if (!newText || !editingMsgId) return;
if (newText === originalEditMsgText) {
cancelEdit();
return;
}
let msgElement = document.getElementById('msg-' + editingMsgId);
if (msgElement) msgElement.style.opacity = '0.5';
let idToEdit = editingMsgId;
cancelEdit(); // Reset UI immediately
$.post('chat_api.php', { action: 'edit_message', id_chat: idToEdit, new_message: newText }, function(res) {
if (msgElement) msgElement.style.opacity = '1';
if (res.status === 'success') {
// Reload messages to ensure formatting consistency
if (activeOccupantId) {
$.post('chat_api.php', { action: 'get_messages', id_occupant: activeOccupantId }, function(res2) {
if(res2.status === 'success') {
renderMessages(res2.data);
}
}, 'json');
}
} else {
Swal.fire('Gagal', res.message || 'Pesan tidak dapat diedit', 'error');
}
}, 'json');
}
// Initial load
$(document).ready(function() {
loadContacts();
renderEmojis('smileys');
setInterval(function(){
if(isSelectionMode) return; // DON'T REFRESH HTML WHILE USER IS SELECTING
if(!document.getElementById('searchInput').value) {
loadContacts();
if(activeOccupantId) {
$.post('chat_api.php', { action: 'get_messages', id_occupant: activeOccupantId }, function(res2) {
if(res2.status === 'success') {
let hist = document.getElementById('chatHistory');
let newHtml = buildMessagesHtml(res2.data);
if(hist.innerHTML !== newHtml) {
let isScrolledBottom = hist.scrollHeight - hist.clientHeight <= hist.scrollTop + 10;
// Update innerHTML instead of appending
hist.innerHTML = newHtml;
if(isScrolledBottom) scrollToBottom();
}
}
}, 'json');
}
}
}, 5000);
});