// common.js const md = window.markdownit(); const contextMenu = document.getElementById('context-menu'); let currentMessageId = null; let currentMessageText = null; function showToast(message) { const toast = document.getElementById('toast'); const toastMessage = document.getElementById('toast-message'); toastMessage.textContent = message; toast.classList.add('show'); setTimeout(() => { toast.classList.remove('show'); }, 3000); } function scrollToBottom(element) { element.scrollTop = element.scrollHeight; } function shouldShowUsername(previousTimestamp, currentTimestamp) { const tenMinutes = 10 * 60 * 1000; return (currentTimestamp - previousTimestamp) > tenMinutes; } function formatLocalTime(utcTimestamp) { const date = new Date(utcTimestamp); const localDate = new Date(date.getTime() - date.getTimezoneOffset() * 60000); const now = new Date(); const today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); const yesterday = new Date(now.getFullYear(), now.getMonth(), now.getDate() - 1); const timeFormatter = { hour: '2-digit', minute: '2-digit' }; const dateFormatter = { year: 'numeric', month: '2-digit', day: '2-digit' }; let formattedTime; if (localDate >= today) { formattedTime = `Today at ${localDate.toLocaleTimeString(undefined, timeFormatter)}`; } else if (localDate >= yesterday) { formattedTime = `Yesterday at ${localDate.toLocaleTimeString(undefined, timeFormatter)}`; } else { formattedTime = `${localDate.toLocaleDateString(undefined, dateFormatter)} at ${localDate.toLocaleTimeString(undefined, timeFormatter)}`; } return formattedTime; } function isImageUrl(url) { return /\.(jpg|jpeg|png|gif|bmp|svg)$/i.test(url); } function appendMessage(messagesList, msg, showUsername, senderProfilePicture) { const currentTimestamp = new Date(msg.timestamp).getTime(); const newMessage = document.createElement('div'); newMessage.classList.add('message'); newMessage.dataset.messageId = msg.id; newMessage.dataset.messageText = msg.content; if (showUsername) { const usernameElement = document.createElement('div'); usernameElement.classList.add('message-sender'); if (msg.sender === username) { usernameElement.classList.add('message-myself-sender'); } const profilePicUrl = senderProfilePicture ? `/cdn/${senderProfilePicture}` : '/cdn/default_profile_picture.png'; usernameElement.innerHTML = ` ${msg.sender} ${msg.sender}
${formatLocalTime(msg.timestamp)}
`; messagesList.appendChild(usernameElement); } if (msg.content_type === 'text') { if (isImageUrl(msg.content)) { newMessage.innerHTML = `Image
${formatLocalTime(msg.timestamp)}
`; } else { newMessage.innerHTML = `${md.render(msg.content)}
${formatLocalTime(msg.timestamp)}
`; } } else if (msg.content_type === 'file') { const isImage = isImageUrl(msg.content); const isVideo = /\.(mp4|webm|ogg)$/i.test(msg.content); if (isImage) { newMessage.innerHTML = `Image
${formatLocalTime(msg.timestamp)}
`; } else if (isVideo) { newMessage.innerHTML = `
${formatLocalTime(msg.timestamp)}
`; } else { newMessage.innerHTML = `Download File
${formatLocalTime(msg.timestamp)}
`; } } messagesList.appendChild(newMessage); scrollToBottom(messagesList); } document.addEventListener('contextmenu', function (event) { const messageElement = event.target.closest('.message'); if (messageElement) { event.preventDefault(); currentMessageId = messageElement.dataset.messageId; currentMessageText = messageElement.dataset.messageText; contextMenu.style.top = `${event.clientY}px`; contextMenu.style.left = `${event.clientX}px`; contextMenu.style.display = 'block'; } else { contextMenu.style.display = 'none'; } }); document.getElementById('copy-text').addEventListener('click', function () { if (currentMessageText) { navigator.clipboard.writeText(currentMessageText).then(() => { showToast('Text copied to clipboard'); }); } contextMenu.style.display = 'none'; }); document.getElementById('copy-id').addEventListener('click', function () { if (currentMessageId) { navigator.clipboard.writeText(currentMessageId).then(() => { showToast('Message ID copied to clipboard'); }); } contextMenu.style.display = 'none'; }); contextMenu.addEventListener('contextmenu', function (event) { event.preventDefault(); }); document.addEventListener('click', function () { contextMenu.style.display = 'none'; });