diff --git a/assets/js/main.js b/assets/js/main.js index e394358..abc797d 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -5,11 +5,33 @@ document.addEventListener('DOMContentLoaded', () => { const messagesList = document.getElementById('messages-list'); const typingIndicator = document.getElementById('typing-indicator'); + function scrollToBottom(force = false) { + if (!messagesList) return; + + // Smart scroll: only scroll if user is already at the bottom or if forced (e.g. sending a message) + const threshold = 150; // pixels margin + const isAtBottom = messagesList.scrollHeight - messagesList.scrollTop <= messagesList.clientHeight + threshold; + + if (force || isAtBottom) { + messagesList.scrollTo({ + top: messagesList.scrollHeight, + behavior: 'smooth' + }); + + // Backup for non-smooth support or rendering delays + setTimeout(() => { + if (force || messagesList.scrollHeight - messagesList.scrollTop <= messagesList.clientHeight + threshold + 200) { + messagesList.scrollTop = messagesList.scrollHeight; + } + }, 100); + } + } + // Emoji list for reactions const EMOJIS = ['👍', '❤️', '😂', '😮', '😢', '🔥', '✅', '🚀', '❓', '💡', '📌', '💯']; // Scroll to bottom - messagesList.scrollTop = messagesList.scrollHeight; + scrollToBottom(true); const currentChannel = new URLSearchParams(window.location.search).get('channel_id') || 1; const currentThread = new URLSearchParams(window.location.search).get('thread_id'); @@ -45,7 +67,6 @@ document.addEventListener('DOMContentLoaded', () => { const data = JSON.parse(msg.data); if (data.channel_id == currentChannel) { appendMessage(data); - messagesList.scrollTop = messagesList.scrollHeight; // Desktop Notifications for mentions if (data.content.includes(`@${window.currentUsername}`) && data.user_id != window.currentUserId) { @@ -174,7 +195,6 @@ document.addEventListener('DOMContentLoaded', () => { const result = JSON.parse(xhr.responseText); if (result.success) { appendMessage(result.message); - messagesList.scrollTop = messagesList.scrollHeight; if (ws && ws.readyState === WebSocket.OPEN) { ws.send(JSON.stringify({ type: 'message', @@ -1417,6 +1437,18 @@ document.addEventListener('DOMContentLoaded', () => { if (!msg || !msg.id) return; if (document.querySelector(`.message-item[data-id="${msg.id}"]`)) return; + // Auto-populate metadata for video platforms if missing + const dmRegexForMeta = /(?:https?:\/\/)?(?:www\.)?(?:dailymotion\.com\/video\/|dai\.ly\/)([a-zA-Z0-9]+)/; + const dmMatchForMeta = msg.content.match(dmRegexForMeta); + if (dmMatchForMeta && !msg.metadata) { + msg.metadata = { + title: 'Dailymotion Video', + url: dmMatchForMeta[0], + image: `https://www.dailymotion.com/thumbnail/video/${dmMatchForMeta[1]}`, + site_name: 'Dailymotion' + }; + } + const messagesList = document.getElementById('messages-list'); const div = document.createElement('div'); div.className = 'message-item'; @@ -1496,11 +1528,11 @@ document.addEventListener('DOMContentLoaded', () => { let videoHtml = ''; if (ytMatch && ytMatch[1]) { - videoHtml = `
`; + videoHtml = ``; } else if (dmMatch && dmMatch[1]) { - videoHtml = ``; + videoHtml = ``; } else if (vimeoMatch && vimeoMatch[1]) { - videoHtml = ``; + videoHtml = ``; } const authorStyle = msg.role_color ? `color: ${msg.role_color};` : ''; @@ -1517,7 +1549,7 @@ document.addEventListener('DOMContentLoaded', () => { ${escapeHTML(msg.content).replace(/\n/g, '