function decodeCanvas(encoded, totalPixels) {
    const decoded = [];
    let bitBuffer = 0;
    let bitsInBuffer = 0;
    let pixelCount = 0;

    for (let i = 0; i < encoded.length; i++) {
        const byte = encoded.charCodeAt(i);

        bitBuffer = (bitBuffer << 8) | byte;
        bitsInBuffer += 8;

        while (bitsInBuffer >= 5
            && pixelCount < totalPixels) {
            bitsInBuffer -= 5;
            const pixel =
                (bitBuffer >> bitsInBuffer) & 0b11111;

            decoded.push(pixel);
            pixelCount++;
        }
    }

    return decoded;
}
S6 - 2025 Mai 2025

E/Place

Client web inspiré de r/place, conçu pour rejoindre un canevas partagé, charger son état puis afficher ses mises à jour en temps réel.

JavaScript Vite Socket.IO Canvas API OIDC JWT

Le projet en quelques mots

E/Place est un rush JavaScript consacré au développement du client web d'un canevas collaboratif, à partir d'une interface et d'un serveur fournis.

Le navigateur rejoint une salle, récupère sa configuration et son image complète, puis reçoit les nouveaux pixels au fil de leur arrivée. Le rendu conservé couvre cette chaîne de chargement ainsi que la connexion à Forge ID. Il ne s'agit pas du développement du serveur E/Place.

Échanges avec les services fournis

Le client utilise trois échanges complémentaires : Forge ID pour obtenir les jetons de connexion, l'API HTTP pour charger les données d'une salle et Socket.IO pour recevoir les événements du canevas. Le serveur local et sa configuration Docker faisaient partie de l'environnement du sujet.

Client JavaScript

Gestion OIDC
Chargement HTTP
Rendu du canevas

Services fournis

Forge ID
API E/Place
Flux Socket.IO

Canevas côté client

Configuration de la salle
Image initiale
Mises à jour des pixels

Fonctionnalités présentes dans le rendu

Connexion OIDC

Redirection vers Forge ID, échange du code d'autorisation contre des jetons, stockage local et tentative de renouvellement avec le refresh token.

Accès à une salle

Lecture du nom de la salle dans l'URL avec repli sur epi-place, ouverture d'une connexion Socket.IO unique et abonnement au flux du canevas.

Chargement du canevas

Récupération de la configuration et des pixels par l'API, décodage des indices de couleur stockés sur cinq bits, puis initialisation du canevas fourni par l'interface.

Mises à jour en temps réel

Écoute des événements pixel-update. Les événements reçus pendant le chargement initial sont mémorisés, puis rejoués une fois le canevas prêt.

Conserver les mises à jour pendant le chargement

L'abonnement au flux est lancé avant le téléchargement du canevas complet. Une liste temporaire évite ainsi de perdre les pixels reçus entre ces deux opérations. Lorsque l'image initiale est affichée, les mises à jour en attente sont appliquées dans l'ordre de réception.

let verif = false;
const listOfPixel = new Array();

socket.on("pixel-update", (data) => {
    const posX = data.result.data.json.posX;
    const posY = data.result.data.json.posY;
    const color = data.result.data.json.color;

    if (verif) {
        renderCanvasUpdate(color, posX, posY);
    } else {
        listOfPixel.push({ x: posX, y: posY, c: color });
    }
});

initCanvas(resres, decode);
verif = true;

listOfPixel.forEach((pix) => {
    renderCanvasUpdate(pix.c, pix.x, pix.y);
});

Synthèse du projet

Travail réalisé dans le rendu

Le code complète le parcours d'authentification, la requête HTTP authentifiée et la connexion Socket.IO nécessaires pour charger et suivre une salle. Il relie ces échanges au canevas fourni et traite l'encodage compact des couleurs.

Ce que le projet m'a apporté

Ce rush m'a fait travailler sur l'ordre des opérations asynchrones, la différence entre un état initial obtenu par HTTP et un flux continu d'événements, ainsi que le parcours d'authentification d'une application web avec OIDC et des jetons JWT.

Projet précédent ERO1 Tous les projets Projet suivant Tiger