Working avatar + english comments

This commit is contained in:
gprunet
2026-01-21 16:53:10 +01:00
parent 5bdf7f0442
commit 173d1a56f3
10 changed files with 43 additions and 111 deletions
+6
View File
@@ -39,6 +39,10 @@ BACKEND
Aucun moyen de changer l'etat de la room de waiting a en cours ou finished
ca attendra le systeme du jeu
21/01 Ajout du service/route pour le systeme d'avatar
permet aux utilisateurs de changer ou supprimer leur avatar actuel
Ajout egalement d'une simple fonction pour recuperer l'avatar d'un utilisateur (pour le frontend)
DATABASE
17/01 Ajout des tables game_rooms, game_players, game_rounds, words
@@ -46,3 +50,5 @@ DATABASE
- joueurs dans la game, leur scores et leur role actuel (dessinateur, devineur)
- historique de la game, qui a dessine quoi precedemment ainsi que les timers des rounds, sera aussi utile si on veut faire les stats de compte a l'avenir.
- contient la liste des mots utilisable par les joueurs
21/01 Ajout de avatar_url dans la table users
+2 -2
View File
@@ -28,8 +28,8 @@ services:
# - "3001:3001"
depends_on:
- database
# volumes:
# //
volumes:
- ./srcs/backend/avatar:/app/avatar
env_file:
- ../.env
networks:
+1
View File
@@ -38,6 +38,7 @@ async function createTables()
username VARCHAR(50) UNIQUE NOT NULL,
password_hash TEXT NOT NULL,
email VARCHAR(100),
avatar_url TEXT DEFAULT '/avatar/default.png',
created_at TIMESTAMP DEFAULT NOW()
);
+4 -4
View File
@@ -5,10 +5,10 @@ import {Server} from 'socket.io';
import authRouter from './routes/auth.js';
import chatRouter from './routes/global_chat.js';
import gameRoomRouter from './routes/game_room.js';
// import avatarRouter from './routes/avatar.js';
import avatarRouter from './routes/avatar.js';
import {waitForDb, createTables, ensureOauthClient} from './db.js';
import setupSocketIO from './services/socket.js';
// import avatarService from './services/avatar.js';
import avatarService from './services/avatar.js';
const app = express();
const server = http.createServer(app);
@@ -38,11 +38,11 @@ async function startServer()
console.warn('OAuth client might already exist or failed to register:', e.message);
}
// app.use('/avatar', express.static(avatarService.AVATAR_DIR));
app.use('/avatar', express.static(avatarService.AVATAR_DIR));
app.use('/api/auth', authRouter);
app.use('/api/global_chat', chatRouter);
app.use('/api/rooms', gameRoomRouter);
// app.use('/api/avatar', avatarRouter);
app.use('/api/avatar', avatarRouter);
app.get('/api', (req, res) => res.send('Backend running'));
server.listen(3001, () =>
+1 -1
View File
@@ -1,7 +1,7 @@
import express from 'express';
import multer from 'multer';
import avatarService from '../services/avatar.js';
import {authenticateToken} from '../middleware/auth.js';
import authenticateToken from '../middleware/auth.js';
const router = express.Router();
+3 -3
View File
@@ -9,7 +9,7 @@ function direBonjour() {
alert("clicked !");
}
// Définir les éléments du menu (structure logique)
// Define the elements of the menu (logical structure)
const menuElement = new Element("menu");
const loginElement = new MenuElement("login");
const registeredElement = new MenuElement("registered");
@@ -17,11 +17,11 @@ const explorerElement = new MenuElement("explorer");
const accueilElement = new MenuElement("accueil");
const globalChatElement = new MenuElement("global_chat");
// Lancement de la grille (commentés si on ne lutilise pas tout de suite)
// Start of the grid (commented if we dont use it yet)
// const gridgreen = new Grid('#143a0fff', -1, 25, 0.12, "normal");
// const gridReverseRed = new Grid('#3a0f0f75', -1, 12.5, 0.09, "reverse");
// Fenêtres et écrans
// Windows and screens
const test = new fenetre();
const loginWindow = new LoginWindow();
const global_chat = new GlobalChat();
+15 -15
View File
@@ -3,7 +3,7 @@ export class GlobalChat extends fenetre {
constructor() {
super(320, 240, "Global Chat");
// Création des éléments
// Creation of the elements
this.output = document.createElement("div");
this.output.className = "chat-output";
@@ -24,12 +24,12 @@ export class GlobalChat extends fenetre {
this.applyStyles();
this.applyEvents();
// Connexion au chat global est déclenchée via des contrôles dédiés
// Connection to the global chat is started via dedicated controls
this.connected = false;
this.createConnectControls();
}
// Crée les contrôles Connect / Reconnect dans la fenêtre du chat
// Create the controls (Connect / Reconnect) in the chat window
createConnectControls() {
this.controls = document.createElement("div");
this.controls.style.display = "flex";
@@ -62,7 +62,7 @@ export class GlobalChat extends fenetre {
}
async reconnect_sockio_global_chat() {
// Déconnecte et reconnecte le socket si nécessaire
// Disconnect and reconnect the socket if necessary
if (this.socket) {
try {
this.socket.close();
@@ -77,7 +77,7 @@ export class GlobalChat extends fenetre {
}
applyStyles() {
// Conteneur principal en flex column
// Main container in flex collumn
this.body.style.display = "flex";
this.body.style.flexDirection = "column";
this.body.style.height = "100%";
@@ -85,7 +85,7 @@ export class GlobalChat extends fenetre {
this.body.style.boxSizing = "border-box";
this.body.style.gap = "10px";
// Zone des messages
// Messages zone
this.output.style.flex = "1";
this.output.style.overflowY = "auto";
this.output.style.padding = "8px";
@@ -95,7 +95,7 @@ export class GlobalChat extends fenetre {
this.output.style.flexDirection = "column";
this.output.style.gap = "10px";
// Conteneur input + bouton
// Input container + button
this.inputContainer.style.display = "flex";
this.inputContainer.style.gap = "8px";
this.inputContainer.style.paddingTop = "8px";
@@ -107,7 +107,7 @@ export class GlobalChat extends fenetre {
this.input.style.borderRadius = "6px";
this.input.style.fontSize = "14px";
// Bouton envoyer
// Sender button
this.sendButton.style.padding = "8px 16px";
this.sendButton.style.background = "#0066cc";
this.sendButton.style.color = "white";
@@ -118,10 +118,10 @@ export class GlobalChat extends fenetre {
}
applyEvents() {
// Envoi avec le bouton
// Send with the button
this.sendButton.addEventListener("click", () => this.sendMessage());
// Envoi avec Entrée
// Send with Enter key
this.input.addEventListener("keypress", (e) => {
if (e.key === "Enter" && !e.shiftKey) {
e.preventDefault();
@@ -130,7 +130,7 @@ export class GlobalChat extends fenetre {
});
}
// Envoie le message courant via Socket.IO
// Send current message via Socket.IO
sendMessage() {
const content = this.input.value.trim();
if (!content) return;
@@ -143,7 +143,7 @@ export class GlobalChat extends fenetre {
return;
}
// Affichage immédiat dans l'interface pour feedback utilisateur
// Immediate display in the interface pour user feedback
const div = document.createElement("div");
div.className = "chat-message";
div.innerHTML = `<strong>Moi:</strong> ${content}`;
@@ -167,7 +167,7 @@ export class GlobalChat extends fenetre {
return;
}
// Si déjà connecté, ne pas tenter de nouveau
// If already connected, dont retry
if (this.socket && this.socket.connected) {
this.output.innerHTML += '<div class="system">Déjà connecté au chat global</div>';
return;
@@ -194,7 +194,7 @@ export class GlobalChat extends fenetre {
reconnectionDelay: 1000,
transports: ["websocket", "polling"]
};
// Optionnel: se connecter via un port alternatif si défini (ex: pour contourner le proxy)
// Optional: connect from an alternative port (ex: to dodge the proxy)
const altPort = window.GLOBAL_CHAT_ALT_PORT;
if (altPort) {
const host = location.hostname || 'localhost';
@@ -218,7 +218,7 @@ export class GlobalChat extends fenetre {
this.output.innerHTML += `<div class="system">Déconnecté du chat (${reason})</div>`;
});
// Réception des messages
// Messages reception
this.socket.on("chat-message", (msg) => {
const div = document.createElement("div");
div.className = "chat-message";
-75
View File
@@ -1,75 +0,0 @@
export class Grid {
constructor(color = '#143a0fff', zIndex = 1, gridSize = 25, speed = 0.35, sens = "normal") {
// Initialisation des propriétés de l'instance
this.canvas = document.createElement('canvas');
this.ctx = this.canvas.getContext('2d');
this.offset = 0;
this.gridSize = gridSize;
this.speed = speed;
this.color = color;
// Configuration du style
document.body.appendChild(this.canvas);
this.canvas.style.position = 'fixed';
this.canvas.style.top = '0';
this.canvas.style.left = '0';
this.canvas.style.zIndex = zIndex;
this.canvas.style.pointerEvents = 'none'; // Pour ne pas bloquer les clics sur les boutons
// Gestion du redimensionnement
window.addEventListener('resize', () => this.resize());
this.resize();
this.draw(sens);
}
resize() {
this.canvas.width = window.innerWidth;
this.canvas.height = window.innerHeight;
}
draw(sens = "normal") {
this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height);
this.ctx.strokeStyle = this.color;
this.ctx.lineWidth = 1;
// Mise à jour de l'offset
this.offset = (this.offset + this.speed) % this.gridSize;
if (sens === "normal") {
// Lignes verticales
for (let x = this.offset; x < this.canvas.width; x += this.gridSize) {
this.ctx.beginPath();
this.ctx.moveTo(x, 0);
this.ctx.lineTo(x, this.canvas.height);
this.ctx.stroke();
}
// Lignes horizontales
for (let y = this.offset; y < this.canvas.height; y += this.gridSize) {
this.ctx.beginPath();
this.ctx.moveTo(0, y);
this.ctx.lineTo(this.canvas.width, y);
this.ctx.stroke();
}
}
//pareillement pour le sens reverse
else if (sens === "reverse") {
// Lignes verticales
for (let x = this.gridSize - this.offset; x < this.canvas.width; x += this.gridSize) {
this.ctx.beginPath();
this.ctx.moveTo(x, 0);
this.ctx.lineTo(x, this.canvas.height);
this.ctx.stroke();
}
// Lignes horizontales
for (let y = this.gridSize - this.offset; y < this.canvas.height; y += this.gridSize) {
this.ctx.beginPath();
this.ctx.moveTo(0, y);
this.ctx.lineTo(this.canvas.width, y);
this.ctx.stroke();
}
}
// Appel récursif pour l'animation
requestAnimationFrame(() => this.draw(sens));
}
}
+1 -1
View File
@@ -10,7 +10,7 @@
<body>
<h1>scribl.lidl_edition</h1>
<!-- Menu principal -->
<!-- Main menu -->
<nav id="menu" aria-label="Menu principal">
<button id="accueil" aria-label="Accueil">Accueil</button>
<button id="explorer" aria-label="Explorer">Explorer</button>
+7 -7
View File
@@ -33,14 +33,14 @@ export class LoginWindow extends fenetre {
this.applyStyles();
this.bindEvents();
// **** AJOUT FONCTION GITHUB ****
// Dans constructor() de LoginWindow
// **** ADDED GITHUB FUNCTION ****
// In constructor() of LoginWindow
this.githubBtn = document.createElement("button");
this.githubBtn.innerText = "Se connecter avec GitHub";
this.githubBtn.style.backgroundColor = "#24292e";
this.githubBtn.style.color = "white";
this.githubBtn.onclick = () => {
// Ouvre le OAuth GitHub dans une popup et reçoit le token via postMessage
// Open the OAUTH Github in a popup and receive the token from postMessage
const w = 600;
const h = 700;
const left = (screen.width - w) / 2;
@@ -59,7 +59,7 @@ export class LoginWindow extends fenetre {
};
this.body.appendChild(this.githubBtn);
this.checkIfAlreadyLoggedIn(); //verifie si l'utilisateur est connecté au démarrage
this.checkIfAlreadyLoggedIn(); // Verify if the user is connected on startup
}
applyStyles() {
@@ -93,13 +93,13 @@ export class LoginWindow extends fenetre {
if (response.ok) {
console.log("connexion ok", data);
// *** STOCKAGE DU TOKEN ***
// *** TOKEN STORAGE ***
if (data.token) {
localStorage.setItem("auth_token", data.token);
this.message.innerText = "Connexion réussie ! Bienvenue.";
this.message.style.color = "#3cff01";
// masquer la fenêtre après 1.5s
// mask the window after 1.5s
setTimeout(() => this.hide(), 1500);
}
@@ -109,7 +109,7 @@ export class LoginWindow extends fenetre {
}
}
else {
// Afficher une erreur utilisateur plus visible
// Show a more visible user error
const errMsg = data && data.message ? data.message : "Échec de la connexion";
this.message.innerText = errMsg;
this.message.style.color = "#ff4d4d";