Ajout de fonctionnalités de mention dans la shoutbox pour les modérateurs Twitch. Implémentation de la gestion des mentions d'utilisateurs avec un système de mise en surbrillance pour les messages contenant des mentions. Mise à jour de l'interface utilisateur pour permettre aux modérateurs de mentionner facilement d'autres utilisateurs et d'améliorer l'interaction dans la shoutbox.

This commit is contained in:
2026-03-06 23:59:04 +01:00
parent 10dd78f630
commit 64c043feb5
2 changed files with 54 additions and 8 deletions
+26 -3
View File
@@ -85,6 +85,8 @@ function userColor(name) {
return colorMap[name];
}
var currentUser = '{{ current_user.username }}';
function esc(t) { var d = document.createElement('div'); d.textContent = t; return d.innerHTML; }
function fmtTime(iso) {
@@ -92,6 +94,22 @@ function fmtTime(iso) {
return d.getHours().toString().padStart(2,'0') + ':' + d.getMinutes().toString().padStart(2,'0');
}
function mentionUser(username) {
var input = document.getElementById('shoutboxInput');
var val = input.value;
var mention = '@' + username + ' ';
if (val && !val.endsWith(' ')) mention = ' ' + mention;
input.value = val + mention;
input.focus();
}
function renderText(text) {
var escaped = esc(text);
var mentioned = currentUser && text.toLowerCase().indexOf('@' + currentUser.toLowerCase()) >= 0;
escaped = escaped.replace(/@(\w+)/g, '<span class="text-indigo-400 font-semibold">@$1</span>');
return { html: escaped, mentioned: mentioned };
}
function addItem(item) {
if (knownIds.has(item.id)) return;
knownIds.add(item.id);
@@ -100,12 +118,16 @@ function addItem(item) {
if (ph) ph.remove();
var line = document.createElement('div');
line.className = 'py-0.5 leading-relaxed';
line.className = 'py-0.5 leading-relaxed rounded px-1';
var time = '<span class="text-gray-500">[' + fmtTime(item.created_at) + ']</span> ';
if (item.type === 'message') {
var c = userColor(item.author);
line.innerHTML = time + '<span style="color:' + c + '" class="font-semibold">&lt;' + esc(item.author) + '&gt;</span> <span class="text-gray-200">' + esc(item.text) + '</span>';
var rendered = renderText(item.text);
line.innerHTML = time + '<span style="color:' + c + '" class="font-semibold cursor-pointer hover:underline" onclick="mentionUser(\'' + esc(item.author).replace(/'/g, "\\'") + '\')">&lt;' + esc(item.author) + '&gt;</span> <span class="text-gray-200">' + rendered.html + '</span>';
if (rendered.mentioned) {
line.className += ' bg-red-900/40 font-bold';
}
} else {
var au = (item.action || '').toUpperCase();
var sc = 'text-red-400';
@@ -135,7 +157,8 @@ function updateOnline(users) {
list.innerHTML = '';
users.forEach(function(u) {
var el = document.createElement('div');
el.className = 'flex items-center gap-1.5 text-xs text-gray-300';
el.className = 'flex items-center gap-1.5 text-xs text-gray-300 cursor-pointer hover:text-white';
el.onclick = function() { mentionUser(u); };
el.innerHTML = '<span class="w-1.5 h-1.5 rounded-full bg-green-500 flex-shrink-0"></span>' + esc(u);
list.appendChild(el);
});
+28 -5
View File
@@ -979,6 +979,7 @@ document.addEventListener('keydown', function(e) {
// =============================
// Shoutbox modérateurs (IRC)
// =============================
var shoutboxCurrentUser = '{{ current_user.username }}';
var shoutboxKnownIds = new Set();
var shoutboxLastTimestamp = '';
var shoutboxAutoScroll = true;
@@ -1025,6 +1026,23 @@ function shoutboxTime(isoStr) {
return d.getHours().toString().padStart(2, '0') + ':' + d.getMinutes().toString().padStart(2, '0');
}
function shoutboxMention(username) {
var input = document.getElementById('shoutboxInput');
var val = input.value;
var mention = '@' + username + ' ';
if (val && !val.endsWith(' ')) mention = ' ' + mention;
input.value = val + mention;
input.focus();
}
function shoutboxRenderText(text) {
var escaped = escapeHtml(text);
var isMentioned = shoutboxCurrentUser && text.toLowerCase().indexOf('@' + shoutboxCurrentUser.toLowerCase()) >= 0;
escaped = escaped.replace(/@(\w+)/g, '<span class="text-indigo-400 font-semibold">@$1</span>');
if (isMentioned) return { html: escaped, mentioned: true };
return { html: escaped, mentioned: false };
}
function addShoutboxItem(item) {
if (shoutboxKnownIds.has(item.id)) return;
shoutboxKnownIds.add(item.id);
@@ -1034,15 +1052,19 @@ function addShoutboxItem(item) {
if (ph) ph.remove();
var line = document.createElement('div');
line.className = 'py-0.5 leading-relaxed';
line.className = 'py-0.5 leading-relaxed rounded px-1';
var time = '<span class="text-gray-500">[' + shoutboxTime(item.created_at) + ']</span> ';
if (item.type === 'message') {
var color = shoutboxColor(item.author);
var rendered = shoutboxRenderText(item.text);
line.innerHTML = time +
'<span style="color:' + color + '" class="font-semibold">&lt;' + escapeHtml(item.author) + '&gt;</span> ' +
'<span class="text-gray-200">' + escapeHtml(item.text) + '</span>';
'<span style="color:' + color + '" class="font-semibold cursor-pointer hover:underline" onclick="shoutboxMention(\'' + escapeHtml(item.author).replace(/'/g, "\\'") + '\')">&lt;' + escapeHtml(item.author) + '&gt;</span> ' +
'<span class="text-gray-200">' + rendered.html + '</span>';
if (rendered.mentioned) {
line.className += ' bg-red-900/40 font-bold';
}
} else {
var actionUpper = (item.action || '').toUpperCase();
var sanctionColor = 'text-red-400';
@@ -1052,7 +1074,7 @@ function addShoutboxItem(item) {
var text = '*** ' + actionUpper;
if (item.moderator) text += ' par ' + item.moderator;
if (item.target) text += ' ' + item.target;
if (item.target) text += ' \u2192 ' + item.target;
if (item.details && item.details !== '-') text += ' (' + item.details + ')';
text += ' ***';
@@ -1077,7 +1099,8 @@ function updateOnlineList(users) {
list.innerHTML = '';
users.forEach(function(u) {
var el = document.createElement('div');
el.className = 'flex items-center gap-1.5 text-xs text-gray-300';
el.className = 'flex items-center gap-1.5 text-xs text-gray-300 cursor-pointer hover:text-white';
el.onclick = function() { shoutboxMention(u); };
el.innerHTML = '<span class="w-1.5 h-1.5 rounded-full bg-green-500 flex-shrink-0"></span>' + escapeHtml(u);
list.appendChild(el);
});