merge done

This commit is contained in:
gprunet
2026-03-05 19:03:34 +01:00
parent 3769ee27a8
commit b3141387b1
9 changed files with 440 additions and 48 deletions
@@ -33,7 +33,6 @@ router.get('/playing', authenticateToken, async(req, res) =>
}
});
// IMPORTANT: This route must be before /:roomId to avoid "current" being interpreted as a roomId
router.get('/current', authenticateToken, async(req, res) =>
{
@@ -150,7 +149,6 @@ router.post('/:roomId/leave', authenticateToken, async(req, res) =>
}
});
// Join a room as spectator
router.post('/:roomId/spectate', authenticateToken, async(req, res) =>
{
@@ -184,5 +182,4 @@ router.post('/:roomId/leave-spectate', authenticateToken, async(req, res) =>
}
});
export default router;
@@ -108,7 +108,6 @@ async function leaveSpectateRoom(roomId, userId)
}
}
async function joinRoom(roomId, userId)
{
const room = await getRoomById(roomId);
@@ -181,7 +180,7 @@ async function getCurrentRoom(userId)
`SELECT r.*
FROM game_rooms r
JOIN game_players gp ON r.id = gp.room_id
WHERE gp.user_id = $1 AND r.status = 'waiting'
WHERE gp.user_id = $1 AND r.status IN ('waiting', 'playing')
LIMIT 1`,
[userId]
);
+32 -19
View File
@@ -600,10 +600,36 @@ function setupSocketIO(io)
const gameState = gameRooms.get(roomId);
if (gameState)
{
const wasDrawer = gameState.drawer === username;
gameState.players = gameState.players.filter(p => p !== username);
delete gameState.scores[username];
io.to(roomId).emit('scores-updated', gameState.scores);
// If the drawer left and there are still enough players, choose a new drawer
if (wasDrawer && gameState.players.length >= 1)
{
// Pick the next player as the new drawer
gameState.currentPlayerIndex = gameState.currentPlayerIndex % gameState.players.length;
const newDrawer = gameState.players[gameState.currentPlayerIndex];
gameState.drawer = newDrawer;
// Reset the word state for the new round
gameState.currentWord = '';
gameState.revealedLetters = [];
gameState.revealedWord = [];
gameState.guessedLetters = [];
gameState.wrongGuesses = 0;
console.log(`Drawer ${username} left, new drawer is ${newDrawer}`);
io.to(roomId).emit('game-drawer-changed', {
newDrawer: newDrawer,
reason: 'drawer_left',
message: `${username} (dessinateur) a quitté, ${newDrawer} devient le nouveau dessinateur`
});
}
}
await checkAndStopSinglePlayerGame(io, roomId, dbRoomId);
@@ -769,7 +795,9 @@ function setupSocketIO(io)
username: socket.user.username
});
console.log(`Spectator ${socket.user.username} disconnected from ${roomId}`);
} else {
}
else
{
// Regular player disconnect
socket.to(roomId).emit('game-player-left', {
username: socket.user.username,
@@ -789,33 +817,18 @@ function setupSocketIO(io)
// Check if game should auto-stop due to single player
await checkAndStopSinglePlayerGame(io, roomId, dbRoomId);
socket.to(roomId).emit('game-player-left', {
username: socket.user.username,
userId: socket.user.userId
});
// Get updated player list and broadcast
if (dbRoomId) {
try {
const players = await gameRoomService.getRoomPlayers(dbRoomId);
io.to(roomId).emit('game-players-updated', { players });
} catch (err) {
console.log('Room may have been deleted on disconnect:', err.message);
}
}
// Broadcast updated rooms list
broadcastRoomsList(io);
}
}
});
});
}
// ── Helpers tetris duel ──────────────────────────────────────────────────
function _tetrisLeave(socket) {
function _tetrisLeave(socket)
{
const code = socket.tetrisRoomCode;
if (!code) return;
const room = tetrisRooms.get(code);
-1
View File
@@ -69,7 +69,6 @@ class App {
initPage() {
const page = document.querySelector('.page');
if (!page) {
console.warn('Page not found');
return;
}
@@ -16,7 +16,9 @@ export class AvatarWindow extends Window {
this.buildUI();
this.bindEvents();
if (localStorage.getItem(STORAGE_KEYS.AUTH_TOKEN)) {
this.loadAvatar();
}
// Listen for login events
eventBus.on(Events.USER_LOGGED_IN, () => this.loadAvatar());
@@ -23,11 +23,14 @@ export const API = {
},
ROOMS: {
LIST: '/api/rooms',
PLAYING: '/api/rooms/playing',
CREATE: '/api/rooms',
GET: (id) => `/api/rooms/${id}`,
PLAYERS: (id) => `/api/rooms/${id}/players`,
JOIN: (id) => `/api/rooms/${id}/join`,
LEAVE: (id) => `/api/rooms/${id}/leave`,
SPECTATE: (id) => `/api/rooms/${id}/spectate`,
LEAVE_SPECTATE: (id) => `/api/rooms/${id}/leave-spectate`,
CURRENT: '/api/rooms/current'
},
STATS: {
+4 -2
View File
@@ -53,11 +53,13 @@ class EventBus {
*/
emit(event, data) {
if (this.listeners.has(event)) {
const listeners = this.listeners.get(event);
this.listeners.get(event).forEach(callback => {
try {
callback(data);
} catch (error) {
console.error(`Error in listener for "${event}":`, error);
}
catch (err) {
// Show that some events are not fully handled, but don't break the app
}
});
}
+343 -12
View File
@@ -36,10 +36,10 @@ export class GameRoomWindow extends Window {
this.updateTabsAccess();
// Verifier si l'utilisateur est deja dans un salon au chargement
if (this.isLoggedIn()) {
const token = localStorage.getItem(STORAGE_KEYS.AUTH_TOKEN);
if (token)
this.checkCurrentRoom();
}
}
buildUI() {
this.tabs = this.createElement('div', CSS.GAMEROOM_TABS);
@@ -49,6 +49,11 @@ export class GameRoomWindow extends Window {
});
this.browseTab.dataset.tab = 'browse';
this.spectatorTab = this.createElement('button', CSS.GAMEROOM_TAB, {
text: 'Spectateur'
});
this.spectatorTab.dataset.tab = 'spectator';
this.createTab = this.createElement('button', CSS.GAMEROOM_TAB, {
text: 'Creer'
});
@@ -60,7 +65,7 @@ export class GameRoomWindow extends Window {
this.lobbyTab.dataset.tab = 'lobby';
this.lobbyTab.style.display = 'none';
this.tabs.append(this.browseTab, this.createTab, this.lobbyTab);
this.tabs.append(this.browseTab, this.spectatorTab, this.createTab, this.lobbyTab);
this.content = this.createElement('div', CSS.GAMEROOM_CONTENT);
@@ -99,9 +104,12 @@ export class GameRoomWindow extends Window {
this.list = this.createElement('div', CSS.GAMEROOM_LIST);
this.spectatorList = this.createElement('div', CSS.GAMEROOM_LIST);
this.spectatorList.style.display = 'none';
this.message = this.createElement('div', CSS.MESSAGE);
this.content.append(this.createContainer, this.lobbyContainer, this.list, this.message);
this.content.append(this.createContainer, this.lobbyContainer, this.list, this.spectatorList, this.message);
this.body.append(this.tabs, this.content);
}
@@ -160,7 +168,7 @@ export class GameRoomWindow extends Window {
// Boutons du jeu
this.gameButtons = this.createElement('div', 'gameroom__game-buttons');
this.backToLobbyBtn = this.createElement('button', [CSS.BTN, CSS.BTN_SECONDARY], { text: 'Retour au lobby' });
this.backToLobbyBtn = this.createElement('button', [CSS.BTN, CSS.BTN_SECONDARY], { text: 'Quitter la partie' });
this.endRoundBtn = this.createElement('button', [CSS.BTN, CSS.BTN_DANGER], { text: 'Terminer le jeu' });
this.gameButtons.append(this.backToLobbyBtn, this.endRoundBtn);
@@ -198,7 +206,7 @@ export class GameRoomWindow extends Window {
this.lastY = 0;
this.canvas.addEventListener('mousedown', (e) => {
if (!this.gameState.isPlaying || !this.isCurrentUserDrawer()) return;
if (!this.gameState.isPlaying || !this.isCurrentUserDrawer() || this.isSpectating) return;
this.isDrawing = true;
[this.lastX, this.lastY] = [e.offsetX, e.offsetY];
});
@@ -365,7 +373,25 @@ export class GameRoomWindow extends Window {
});
this.socket.on('game-player-left', (data) => {
console.log(`${data.username} left the room`);
this.showMessage(`${data.username} a quitté le salon`, 'info');
if (this.gameState.isPlaying)
{
if (this.gameState.players)
this.gameState.players = this.gameState.players.filter(p => p !== data.username);
}
if (this.gameState.scores)
{
delete this.gameState.scores[data.username];
this.updateScoresDisplay(this.gameState.scores);
}
// Note: If the drawer left, the server will emit 'game-drawer-changed'
// with the new drawer, so we don't need to handle it here
if (this.currentRoom && !this.gameState.isPlaying)
this.loadLobby();
});
// Game started
@@ -384,6 +410,12 @@ export class GameRoomWindow extends Window {
this.setupRound();
});
// Game start error
this.socket.on('game-start-error', (data) => {
console.error('Game start error:', data.error);
this.showMessage(data.error || 'Impossible de démarrer la partie', 'error');
});
// Word was set by drawer
this.socket.on('game-word-set', (data) => {
console.log(`Word set by ${data.drawer}, length: ${data.wordLength}`);
@@ -396,6 +428,13 @@ export class GameRoomWindow extends Window {
}
this.updateWordDisplay();
// Don't change UI for spectators
if (this.isSpectating) {
this.currentDrawerInfo.textContent = '👁️ MODE SPECTATEUR - Vous regardez la partie';
return;
}
this.currentDrawerInfo.textContent = `${data.drawer} dessine (${data.wordLength} lettres)`;
// Enable guess input for non-drawers
@@ -451,7 +490,22 @@ export class GameRoomWindow extends Window {
// Game ended
this.socket.on('game-ended', () => {
// If spectating, return to spectator list
if (this.isSpectating) {
this.resetGameUI();
this.currentRoom = null;
this.isSpectating = false;
this.switchTab('spectator');
this.showMessage('La partie est terminée', 'info');
} else {
this.resetGameUI();
this.loadLobby();
}
});
// Game message from server
this.socket.on('game-message', (data) => {
this.showMessage(data.message, data.type || 'info');
});
// Sync state for late joiners
@@ -463,12 +517,25 @@ export class GameRoomWindow extends Window {
this.gameState.revealedLetters = data.revealedLetters || [];
this.gameState.revealedWord = data.revealedWord || new Array(data.wordLength).fill('_');
this.gameState.players = data.players;
this.gameState.scores = data.scores || {};
this.showGameUI();
this.updateWordDisplay();
// Update scores display
if (data.scores) {
this.updateScoresDisplay(data.scores);
}
this.currentDrawerInfo.textContent = `${data.drawer} dessine (${data.wordLength} lettres)`;
if (!this.isCurrentUserDrawer()) {
// Don't enable input for spectators
if (this.isSpectating) {
this.guessContainer.style.display = 'none';
this.wordInputContainer.style.display = 'none';
this.drawTools.style.display = 'none';
this.currentDrawerInfo.textContent = '👁️ MODE SPECTATEUR - Vous regardez la partie';
} else if (!this.isCurrentUserDrawer()) {
this.guessContainer.style.display = 'flex';
if (data.wordLength > 0) {
this.letterInput.disabled = false;
@@ -482,13 +549,75 @@ export class GameRoomWindow extends Window {
}
}
});
// Spectator events
this.socket.on('game-spectate-joined', (data) => {
console.log('Successfully joined as spectator:', data.roomId);
this.isSpectating = true;
// Prepare UI for spectating
this.spectatorList.style.display = 'none';
this.list.style.display = 'none';
this.createContainer.style.display = 'none';
this.lobbyContainer.style.display = 'flex';
// Hide lobby elements, keep game container for when state syncs
this.playerList.style.display = 'none';
this.lobbyButtons.style.display = 'none';
this.lobbyTitle.textContent = 'Mode Spectateur';
this.showMessage('Vous regardez la partie...', 'success');
// The game state will be synced via game-state-sync event
});
this.socket.on('game-spectate-error', (data) => {
console.error('Spectate error:', data.error);
this.showMessage(data.error || 'Impossible de regarder cette partie', 'error');
});
this.socket.on('game-spectator-joined', (data) => {
console.log(`Spectator ${data.username} joined`);
});
this.socket.on('game-spectator-left', (data) => {
console.log(`Spectator ${data.username} left`);
});
// Drawer changed (when drawer leaves during game)
this.socket.on('game-drawer-changed', (data) => {
console.log('Drawer changed:', data);
this.showMessage(data.message, 'info');
// Update game state with new drawer
this.gameState.drawer = data.newDrawer;
this.gameState.currentPlayerIndex = this.gameState.players.indexOf(data.newDrawer);
// Reset round state
this.gameState.currentWord = '';
this.gameState.wordLength = 0;
this.gameState.revealedLetters = [];
this.gameState.revealedWord = [];
this.gameState.guessedLetters = [];
// Clear canvas and history
this.clearCanvas();
this.guessHistory.innerHTML = '';
this.wordDisplay.textContent = '';
// Setup UI for new round with new drawer
this.setupRound();
});
}
disconnectGameSocket() {
if (this.socket) {
if (this.isSpectating) {
this.socket.emit('game-leave-spectate');
} else {
this.socket.emit('game-leave-room');
}
}
}
// ============================================
// UI HELPERS
@@ -533,13 +662,14 @@ export class GameRoomWindow extends Window {
this.currentTab = tabName;
[this.browseTab, this.createTab, this.lobbyTab].forEach(tab => {
[this.browseTab, this.spectatorTab, this.createTab, this.lobbyTab].forEach(tab => {
tab.classList.toggle(CSS.GAMEROOM_TAB_ACTIVE, tab.dataset.tab === tabName);
});
this.createContainer.style.display = tabName === 'create' ? 'flex' : 'none';
this.lobbyContainer.style.display = tabName === 'lobby' ? 'flex' : 'none';
this.list.style.display = tabName === 'browse' ? 'flex' : 'none';
this.spectatorList.style.display = tabName === 'spectator' ? 'flex' : 'none';
this.loadCurrentTab();
}
@@ -551,6 +681,10 @@ export class GameRoomWindow extends Window {
// Connect to socket to receive real-time room updates
this.ensureSocketConnected();
break;
case 'spectator':
this.loadPlayingRooms();
this.ensureSocketConnected();
break;
case 'create':
this.message.textContent = '';
this.ensureSocketConnected();
@@ -776,6 +910,123 @@ export class GameRoomWindow extends Window {
}
}
createSpectatorRoomItem(room) {
const item = this.createElement('div', CSS.GAMEROOM_ITEM);
const name = this.createElement('span', CSS.GAMEROOM_NAME, {
text: room.name
});
const players = this.createElement('span', CSS.GAMEROOM_PLAYERS, {
text: `${room.player_count || 0}/${room.max_players || 8}`
});
const status = this.createElement('span', 'gameroom__status', {
text: '🎮 En cours'
});
status.style.color = '#4CAF50';
status.style.fontWeight = 'bold';
const actions = this.createElement('div', CSS.GAMEROOM_ACTIONS);
const spectateBtn = this.createElement('button', [CSS.BTN, CSS.BTN_PRIMARY], {
text: 'Regarder'
});
spectateBtn.addEventListener('click', () => this.spectateRoom(room.id));
actions.appendChild(spectateBtn);
item.append(name, players, status, actions);
return item;
}
async loadPlayingRooms() {
const token = localStorage.getItem(STORAGE_KEYS.AUTH_TOKEN);
if (!token) {
this.showMessage('Connectez-vous pour voir les parties en cours', 'info');
return;
}
try {
const response = await fetch(API.ROOMS.PLAYING, {
headers: this.getHeaders()
});
const data = await response.json();
if (!response.ok) {
this.showMessage(data.error || 'Erreur', 'error');
return;
}
this.renderPlayingRoomsList(data || []);
} catch (error) {
console.error('Load playing rooms error:', error);
this.showMessage('Erreur de connexion', 'error');
}
}
renderPlayingRoomsList(rooms) {
this.spectatorList.innerHTML = '';
this.message.textContent = '';
if (rooms.length === 0) {
this.showMessage('Aucune partie en cours', 'info');
return;
}
rooms.forEach(room => {
const item = this.createSpectatorRoomItem(room);
this.spectatorList.appendChild(item);
});
}
async spectateRoom(roomId) {
const token = localStorage.getItem(STORAGE_KEYS.AUTH_TOKEN);
if (!token) {
this.showMessage('Connectez-vous pour regarder', 'info');
return;
}
// Check if user is already in a room as a player
if (this.currentRoom && !this.isSpectating) {
this.showMessage('Vous êtes déjà dans un salon. Quittez-le d\'abord.', 'error');
return;
}
// Check if already spectating another game
if (this.isSpectating && this.currentRoom && this.currentRoom.id !== roomId) {
this.showMessage('Vous regardez déjà une autre partie', 'error');
return;
}
try {
const response = await fetch(API.ROOMS.SPECTATE(roomId), {
method: 'POST',
headers: this.getHeaders()
});
const data = await response.json();
if (!response.ok) {
this.showMessage(data.error || 'Impossible de regarder cette partie', 'error');
return;
}
// Store room info and mark as spectating
this.currentRoom = data;
this.isSpectating = true;
// Join as spectator via socket
await this.ensureSocketConnected();
if (this.socket?.connected) {
this.socket.emit('game-spectate-room', { roomId: roomId });
}
this.showMessage('Connexion à la partie...', 'info');
} catch (error) {
console.error('Spectate room error:', error);
this.showMessage('Erreur de connexion', 'error');
}
}
async joinRoom(roomId) {
const token = localStorage.getItem(STORAGE_KEYS.AUTH_TOKEN);
if (!token) {
@@ -844,6 +1095,8 @@ export class GameRoomWindow extends Window {
async loadLobby() {
if (!this.currentRoom) return;
this.gameState.scores = {};
try {
const response = await fetch(API.ROOMS.PLAYERS(this.currentRoom.id), {
headers: this.getHeaders()
@@ -870,6 +1123,10 @@ export class GameRoomWindow extends Window {
text: 'Aucun joueur'
});
this.playerList.appendChild(empty);
// Disable start button if no players
this.startGameBtn.disabled = true;
this.startGameBtn.style.opacity = '0.5';
this.startGameBtn.title = 'Il faut au moins 2 joueurs';
return;
}
@@ -899,6 +1156,17 @@ export class GameRoomWindow extends Window {
item.append(avatar, name, statsContainer);
this.playerList.appendChild(item);
});
// Enable/disable start button based on player count
if (players.length < 2) {
this.startGameBtn.disabled = true;
this.startGameBtn.style.opacity = '0.5';
this.startGameBtn.title = 'Il faut au moins 2 joueurs';
} else {
this.startGameBtn.disabled = false;
this.startGameBtn.style.opacity = '1';
this.startGameBtn.title = '';
}
}
async leaveRoom() {
@@ -941,6 +1209,11 @@ export class GameRoomWindow extends Window {
}
showMessage(text, type = 'info') {
// Clear any existing timeout
if (this.messageTimeout) {
clearTimeout(this.messageTimeout);
}
this.message.textContent = text;
this.message.className = CSS.MESSAGE;
@@ -951,6 +1224,12 @@ export class GameRoomWindow extends Window {
} else {
this.message.classList.add(CSS.MESSAGE_INFO);
}
// Auto-clear message after 5 seconds
this.messageTimeout = setTimeout(() => {
this.message.textContent = '';
this.message.className = CSS.MESSAGE;
}, 5000);
}
// ============================================
@@ -978,6 +1257,23 @@ export class GameRoomWindow extends Window {
this.lobbyButtons.style.display = 'none';
this.clearCanvas();
this.guessHistory.innerHTML = '';
// If spectating, show indicator and disable interactions
if (this.isSpectating) {
this.currentDrawerInfo.textContent = '👁️ MODE SPECTATEUR - Vous regardez la partie';
this.currentDrawerInfo.style.backgroundColor = '#2196F3';
this.currentDrawerInfo.style.color = 'white';
this.currentDrawerInfo.style.padding = '8px';
this.currentDrawerInfo.style.borderRadius = '4px';
this.currentDrawerInfo.style.textAlign = 'center';
// Change button text for spectators
this.backToLobbyBtn.textContent = 'Arrêter de regarder';
this.endRoundBtn.style.display = 'none'; // Hide end game button for spectators
} else {
this.backToLobbyBtn.textContent = 'Quitter la partie';
this.endRoundBtn.style.display = 'inline-block';
}
}
resetGameUI() {
@@ -987,6 +1283,21 @@ export class GameRoomWindow extends Window {
this.gameState.revealedLetters = [];
this.gameState.revealedWord = [];
this.gameState.drawer = null;
this.isSpectating = false;
this.gameState.scores = {};
this.gameState.players = [];
this.gameState.currentPlayerIndex = 0;
this.gameState.guessedLetters = [];
// Clear scores display
if (this.scoresDisplay)
this.scoresDisplay.textContent = '';
if (this.guessHistory)
this.guessHistory.innerHTML = '';
this.clearCanvas();
this.gameContainer.style.display = 'none';
this.playerList.style.display = 'flex';
@@ -996,6 +1307,12 @@ export class GameRoomWindow extends Window {
this.guessContainer.style.display = 'none';
this.drawTools.style.display = 'none';
// Reset spectator styling
this.currentDrawerInfo.style.backgroundColor = '';
this.currentDrawerInfo.style.color = '';
this.currentDrawerInfo.style.padding = '';
this.currentDrawerInfo.style.borderRadius = '';
this.currentDrawerInfo.style.textAlign = '';
this.currentDrawerInfo.classList.remove('gameroom__drawer-info--winner');
}
@@ -1010,8 +1327,8 @@ export class GameRoomWindow extends Window {
console.log('Players found:', players);
if (players.length < 1) {
this.showMessage('Il faut au moins 1 joueur pour jouer', 'error');
if (players.length < 2) {
this.showMessage('Il faut au moins 2 joueurs pour commencer', 'error');
return;
}
@@ -1048,6 +1365,15 @@ export class GameRoomWindow extends Window {
this.guessHistory.innerHTML = '';
this.clearCanvas();
// Spectators cannot interact
if (this.isSpectating) {
this.wordInputContainer.style.display = 'none';
this.guessContainer.style.display = 'none';
this.drawTools.style.display = 'none';
this.currentDrawerInfo.textContent = '👁️ MODE SPECTATEUR - Vous regardez la partie';
return;
}
if (this.isCurrentUserDrawer()) {
// Drawer chooses a word
this.wordInputContainer.style.display = 'flex';
@@ -1254,9 +1580,14 @@ export class GameRoomWindow extends Window {
}
backToLobby() {
if (this.socket?.connected) {
this.socket.emit('leave-room-during-game');
}
// Return to lobby without ending game for others
this.resetGameUI();
this.loadLobby();
this.exitLobby();
this.showMessage('Vous avez quitté la partie', 'info');
}
endGame() {
+48 -2
View File
@@ -17,6 +17,8 @@ export class GlobalChat extends Window {
this.socket = null;
this.connected = false;
this.friendIds = new Set();
this.currentUserId = null;
this.currentUsername = null;
this.buildUI();
this.bindEvents();
@@ -169,6 +171,19 @@ export class GlobalChat extends Window {
await this.connect();
}
decodeToken(token)
{
try
{
const payload = token.split('.')[1];
return (JSON.parse(atob(payload)));
}
catch
{
return (null);
}
}
/**
* Connects to the Socket.IO server
*/
@@ -180,6 +195,13 @@ export class GlobalChat extends Window {
return;
}
const tokenData = this.decodeToken(token);
if (tokenData) {
this.currentUserId = tokenData.id || tokenData.userId || tokenData.user_id || tokenData.sub || null;
this.currentUsername = tokenData.username || tokenData.name || null;
}
if (this.socket?.connected) {
this.addSystemMessage('Already connected to global chat');
return;
@@ -239,6 +261,7 @@ export class GlobalChat extends Window {
this.socket.on('connect', () => {
console.log('Socket connected, ID:', this.socket.id);
this.connected = true;
this.output.innerHTML = '';
this.addSystemMessage('Connected to global chat', 'success');
eventBus.emit(Events.CHAT_CONNECTED, { socketId: this.socket.id });
});
@@ -262,15 +285,38 @@ export class GlobalChat extends Window {
// Display recent messages
data.messages.forEach(msg => {
const isFriend = this.friendIds.has(msg.sender_id);
this.addChatMessage(msg.username, msg.content, false, isFriend);
const isOwn = this.isOwnMessage(msg);
const isFriend = !isOwn && this.friendIds.has(msg.sender_id);
const displayUsername = isOwn ? 'Me' : msg.username;
this.addChatMessage(displayUsername, msg.content, isOwn, isFriend);
});
});
this.socket.on('chat-message', (msg) => {
const isOwn = this.isOwnMessage(msg);
if (isOwn)
return;
const isFriend = this.friendIds.has(msg.sender_id);
this.addChatMessage(msg.username, msg.content, false, isFriend);
eventBus.emit(Events.CHAT_MESSAGE_RECEIVED, msg);
});
}
isOwnMessage(msg)
{
if (this.currentUserId !== null && msg.sender_id !== undefined && msg.sender_id !== null)
{
if (String(this.currentUserId) === String(msg.sender_id))
return (true);
}
if (this.currentUsername && msg.username)
{
if (this.currentUsername.toLowerCase() === msg.username.toLowerCase())
return (true);
}
return (false);
}
}