mirror of
https://gitlab.com/animath/si/plateforme.git
synced 2025-06-21 09:18:23 +02:00
Store what messages are read
Signed-off-by: Emmy D'Anello <emmy.danello@animath.fr>
This commit is contained in:
@ -70,29 +70,8 @@ function setChannels(new_channels) {
|
||||
categoryLists[category].parentElement.classList.add('d-none')
|
||||
}
|
||||
|
||||
for (let channel of new_channels) {
|
||||
channels[channel['id']] = channel
|
||||
if (!messages[channel['id']])
|
||||
messages[channel['id']] = new Map()
|
||||
|
||||
let categoryList = categoryLists[channel['category']]
|
||||
categoryList.parentElement.classList.remove('d-none')
|
||||
|
||||
let navItem = document.createElement('li')
|
||||
navItem.classList.add('list-group-item')
|
||||
navItem.id = `tab-channel-${channel['id']}`
|
||||
navItem.setAttribute('data-bs-dismiss', 'offcanvas')
|
||||
navItem.onclick = () => selectChannel(channel['id'])
|
||||
categoryList.appendChild(navItem)
|
||||
|
||||
let channelButton = document.createElement('button')
|
||||
channelButton.classList.add('nav-link')
|
||||
channelButton.type = 'button'
|
||||
channelButton.innerText = channel['name']
|
||||
navItem.appendChild(channelButton)
|
||||
|
||||
fetchMessages(channel['id'])
|
||||
}
|
||||
for (let channel of new_channels)
|
||||
addChannel(channel, categoryLists)
|
||||
|
||||
if (new_channels && (!selected_channel_id || !channels[selected_channel_id])) {
|
||||
if (window.location.hash) {
|
||||
@ -107,6 +86,38 @@ function setChannels(new_channels) {
|
||||
}
|
||||
}
|
||||
|
||||
async function addChannel(channel, categoryLists) {
|
||||
channels[channel['id']] = channel
|
||||
if (!messages[channel['id']])
|
||||
messages[channel['id']] = new Map()
|
||||
|
||||
let categoryList = categoryLists[channel['category']]
|
||||
categoryList.parentElement.classList.remove('d-none')
|
||||
|
||||
let navItem = document.createElement('li')
|
||||
navItem.classList.add('list-group-item')
|
||||
navItem.id = `tab-channel-${channel['id']}`
|
||||
navItem.setAttribute('data-bs-dismiss', 'offcanvas')
|
||||
navItem.onclick = () => selectChannel(channel['id'])
|
||||
categoryList.appendChild(navItem)
|
||||
|
||||
let channelButton = document.createElement('button')
|
||||
channelButton.classList.add('nav-link')
|
||||
channelButton.type = 'button'
|
||||
channelButton.innerText = channel['name']
|
||||
navItem.appendChild(channelButton)
|
||||
|
||||
let unreadBadge = document.createElement('span')
|
||||
unreadBadge.classList.add('badge', 'rounded-pill', 'text-bg-light', 'ms-2')
|
||||
unreadBadge.id = `unread-messages-${channel['id']}`
|
||||
unreadBadge.innerText = channel.unread_messages || 0
|
||||
if (!channel.unread_messages)
|
||||
unreadBadge.classList.add('d-none')
|
||||
channelButton.appendChild(unreadBadge)
|
||||
|
||||
fetchMessages(channel['id'])
|
||||
}
|
||||
|
||||
function receiveMessage(message) {
|
||||
let scrollableContent = document.getElementById('chat-messages')
|
||||
let isScrolledToBottom = scrollableContent.scrollHeight - scrollableContent.clientHeight <= scrollableContent.scrollTop + 1
|
||||
@ -165,6 +176,32 @@ function receiveFetchedMessages(data) {
|
||||
redrawMessages()
|
||||
}
|
||||
|
||||
function markMessageAsRead(data) {
|
||||
for (let message of data['messages']) {
|
||||
let stored_message = messages[message['channel_id']].get(message['id'])
|
||||
if (stored_message)
|
||||
stored_message['read'] = true
|
||||
}
|
||||
redrawMessages()
|
||||
updateUnreadBadges(data['unread_messages'])
|
||||
}
|
||||
|
||||
function updateUnreadBadges(unreadMessages) {
|
||||
console.log(unreadMessages)
|
||||
for (let channel of Object.values(channels)) {
|
||||
let unreadMessagesChannel = unreadMessages[channel['id']] || 0
|
||||
console.log(channel, unreadMessagesChannel)
|
||||
channel.unread_messages = unreadMessagesChannel
|
||||
|
||||
let unreadBadge = document.getElementById(`unread-messages-${channel['id']}`)
|
||||
unreadBadge.innerText = unreadMessagesChannel
|
||||
if (unreadMessagesChannel)
|
||||
unreadBadge.classList.remove('d-none')
|
||||
else
|
||||
unreadBadge.classList.add('d-none')
|
||||
}
|
||||
}
|
||||
|
||||
function startPrivateChat(data) {
|
||||
let channel = data['channel']
|
||||
if (!channel) {
|
||||
@ -194,6 +231,8 @@ function redrawMessages() {
|
||||
let newTimestamp = new Date(message['timestamp'])
|
||||
if ((newTimestamp - lastTimestamp) / 1000 < 60 * 10) {
|
||||
let messageContentDiv = document.createElement('div')
|
||||
messageContentDiv.classList.add('message')
|
||||
messageContentDiv.setAttribute('data-message-id', message['id'])
|
||||
lastContentDiv.appendChild(messageContentDiv)
|
||||
let messageContentSpan = document.createElement('span')
|
||||
messageContentSpan.innerText = message['content']
|
||||
@ -227,6 +266,8 @@ function redrawMessages() {
|
||||
messageElement.appendChild(contentDiv)
|
||||
|
||||
let messageContentDiv = document.createElement('div')
|
||||
messageContentDiv.classList.add('message')
|
||||
messageContentDiv.setAttribute('data-message-id', message['id'])
|
||||
contentDiv.appendChild(messageContentDiv)
|
||||
let messageContentSpan = document.createElement('span')
|
||||
messageContentSpan.innerText = message['content']
|
||||
@ -243,6 +284,8 @@ function redrawMessages() {
|
||||
fetchMoreButton.classList.add('d-none')
|
||||
else
|
||||
fetchMoreButton.classList.remove('d-none')
|
||||
|
||||
messageList.dispatchEvent(new CustomEvent('updatemessages'))
|
||||
}
|
||||
|
||||
function removeAllPopovers() {
|
||||
@ -370,6 +413,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
case 'fetch_messages':
|
||||
receiveFetchedMessages(data)
|
||||
break
|
||||
case 'mark_read':
|
||||
markMessageAsRead(data)
|
||||
break
|
||||
case 'start_private_chat':
|
||||
startPrivateChat(data)
|
||||
break
|
||||
@ -435,6 +481,51 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
})
|
||||
}
|
||||
|
||||
function setupReadTracker() {
|
||||
const scrollableContent = document.getElementById('chat-messages')
|
||||
const messagesList = document.getElementById('message-list')
|
||||
let markReadBuffer = []
|
||||
let markReadTimeout = null
|
||||
|
||||
scrollableContent.addEventListener('scroll', () => {
|
||||
if (scrollableContent.clientHeight - scrollableContent.scrollTop === scrollableContent.scrollHeight
|
||||
&& !document.getElementById('fetch-previous-messages').classList.contains('d-none')) {
|
||||
// If the user is at the top of the chat, fetch previous messages
|
||||
fetchPreviousMessages()}
|
||||
|
||||
markVisibleMessagesAsRead()
|
||||
})
|
||||
|
||||
messagesList.addEventListener('updatemessages', () => markVisibleMessagesAsRead())
|
||||
|
||||
function markVisibleMessagesAsRead() {
|
||||
let viewport = scrollableContent.getBoundingClientRect()
|
||||
|
||||
for (let item of messagesList.querySelectorAll('.message')) {
|
||||
let message = messages[selected_channel_id].get(parseInt(item.getAttribute('data-message-id')))
|
||||
if (!message.read) {
|
||||
let rect = item.getBoundingClientRect()
|
||||
if (rect.top >= viewport.top && rect.bottom <= viewport.bottom) {
|
||||
message.read = true
|
||||
markReadBuffer.push(message['id'])
|
||||
if (markReadTimeout)
|
||||
clearTimeout(markReadTimeout)
|
||||
markReadTimeout = setTimeout(() => {
|
||||
socket.send(JSON.stringify({
|
||||
'type': 'mark_read',
|
||||
'message_ids': markReadBuffer,
|
||||
}))
|
||||
markReadBuffer = []
|
||||
markReadTimeout = null
|
||||
}, 3000)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
markVisibleMessagesAsRead()
|
||||
}
|
||||
|
||||
function setupPWAPrompt() {
|
||||
let deferredPrompt = null
|
||||
|
||||
@ -460,5 +551,6 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
|
||||
setupSocket()
|
||||
setupSwipeOffscreen()
|
||||
setupReadTracker()
|
||||
setupPWAPrompt()
|
||||
})
|
||||
|
Reference in New Issue
Block a user