plateforme-tfjm2/chat/static/chat.js

134 lines
3.9 KiB
JavaScript
Raw Normal View History

(async () => {
// check notification permission
// This is useful to alert people that they should do something
await Notification.requestPermission()
})()
let channels = {}
let selected_channel_id = null
/**
* Display a new notification with the given title and the given body.
* @param title The title of the notification
* @param body The body of the notification
* @param timeout The time (in milliseconds) after that the notification automatically closes. 0 to make indefinite. Default to 5000 ms.
* @return Notification
*/
function showNotification(title, body, timeout = 5000) {
let notif = new Notification(title, {'body': body, 'icon': "/static/tfjm.svg"})
if (timeout)
setTimeout(() => notif.close(), timeout)
return notif
}
function selectChannel(channel_id) {
let channel = channels[channel_id]
if (!channel) {
console.error('Channel not found:', channel_id)
return
}
selected_channel_id = channel_id
let channelTitle = document.getElementById('channel-title')
channelTitle.innerText = channel['name']
let messageInput = document.getElementById('input-message')
messageInput.disabled = !channel['write_access']
}
function sendMessage() {
let messageInput = document.getElementById('input-message')
let message = messageInput.value
messageInput.value = ''
if (!message) {
return
}
socket.send(JSON.stringify({
'type': 'send_message',
'channel_id': selected_channel_id,
'content': message,
}))
}
function setChannels(new_channels) {
channels = {}
for (let channel of new_channels) {
channels[channel['id']] = channel
}
if (new_channels && (!selected_channel_id || !channels[selected_channel_id])) {
selectChannel(Object.keys(channels)[0])
}
}
function receiveMessage(message) {
let messageList = document.getElementById('message-list')
let messageElement = document.createElement('li')
messageElement.classList.add('list-group-item')
messageList.appendChild(messageElement)
let authorDiv = document.createElement('div')
authorDiv.classList.add('text-muted', 'fw-bold')
authorDiv.innerText = message['author']
messageElement.appendChild(authorDiv)
let contentDiv = document.createElement('div')
contentDiv.innerText = message['content']
messageElement.appendChild(contentDiv)
}
document.addEventListener('DOMContentLoaded', () => {
/**
* Process the received data from the server.
* @param data The received message
*/
function processMessage(data) {
// TODO Implement chat protocol
switch (data['type']) {
case 'fetch_channels':
setChannels(data['channels'])
break
case 'send_message':
receiveMessage(data)
break
default:
console.log(data)
console.error('Unknown message type:', data['type'])
break
}
}
function setupSocket(nextDelay = 1000) {
// Open a global websocket
socket = new WebSocket(
(document.location.protocol === 'https:' ? 'wss' : 'ws') + '://' + window.location.host + '/ws/chat/'
)
// Listen on websockets and process messages from the server
socket.addEventListener('message', e => {
// Parse received data as JSON
const data = JSON.parse(e.data)
processMessage(data)
})
// Manage errors
socket.addEventListener('close', e => {
console.error('Chat socket closed unexpectedly, restarting…')
setTimeout(() => setupSocket(2 * nextDelay), nextDelay)
})
socket.addEventListener('open', e => {
socket.send(JSON.stringify({
'type': 'fetch_channels',
}))
})
}
setupSocket()
})