From 6643d495bdc9f0cd39a60aa41818a09db9ac3692 Mon Sep 17 00:00:00 2001 From: NigeParis Date: Wed, 10 Dec 2025 13:10:59 +0100 Subject: [PATCH] Added Global Message for Next Game - Bug Fixed on Double Displaying Ping Buddies --- frontend/src/chat/chat.css | 27 +++++++++ frontend/src/pages/chat/chat.html | 10 +++- frontend/src/pages/chat/chat.ts | 87 ++++++++++++++++++++------- src/@shared/src/utils/index.ts | 8 +++ src/chat/src/app.ts | 98 +++++++++++++++++++------------ 5 files changed, 170 insertions(+), 60 deletions(-) diff --git a/frontend/src/chat/chat.css b/frontend/src/chat/chat.css index 993c029..b308418 100644 --- a/frontend/src/chat/chat.css +++ b/frontend/src/chat/chat.css @@ -230,6 +230,33 @@ div-private { right-12 } + +.popUpMessage { + @apply + bg-white + p-6 rounded-xl + shadow-xl + w-[800px] + h-[100px] + p-[10px] + border-1 + border-black + +} + +.gamePopup { + @apply + fixed + inset-0 + bg-black/50 + flex + justify-center + items-center; +} + + + + .hidden{ display: none; } \ No newline at end of file diff --git a/frontend/src/pages/chat/chat.html b/frontend/src/pages/chat/chat.html index bf06259..87b57be 100644 --- a/frontend/src/pages/chat/chat.html +++ b/frontend/src/pages/chat/chat.html @@ -1,6 +1,7 @@
+

ChatterBox


@@ -26,9 +27,6 @@

Ping Buddies

- Marks
+
diff --git a/frontend/src/pages/chat/chat.ts b/frontend/src/pages/chat/chat.ts index ea68dfd..fb18ecb 100644 --- a/frontend/src/pages/chat/chat.ts +++ b/frontend/src/pages/chat/chat.ts @@ -87,10 +87,12 @@ function addMessage(text: string) { return ; }; -function clearText() { +function clear(senderSocket: Socket) { const chatWindow = document.getElementById("t-chatbox") as HTMLDivElement; if (!chatWindow) return; chatWindow.innerHTML = ""; + // senderSocket.emit('nextGame'); + } function isLoggedIn() { @@ -106,11 +108,11 @@ function inviteToPlayPong(profil: ClientProfil, senderSocket: Socket) { -function actionBtnPopUpClear(profil: ClientProfil) { +function actionBtnPopUpClear(profil: ClientProfil, senderSocket: Socket) { setTimeout(() => { const clearTextBtn = document.querySelector("#popup-b-clear"); clearTextBtn?.addEventListener("click", () => { - clearText(); + clear(senderSocket); }); }, 0) }; @@ -240,8 +242,9 @@ async function listBuddies(socket: Socket, buddies: HTMLDivElement, listBuddies: }); buddiesElement.addEventListener("dblclick", () => { - console.log("Open profile:", listBuddies); + console.log("Open profile:", listBuddies); getProfil(socket, listBuddies); + sendtextbox.value = ""; }); buddies.appendChild(buddiesElement); @@ -387,12 +390,32 @@ async function openProfilePopup(profil: ClientProfil) {
About: '${profil.text}'
`; - const profilList = document.getElementById("profile-modal") ?? null; + const profilList = document.getElementById("profile-modal") ?? null; if (profilList) profilList.classList.remove("hidden"); // The popup now exists → attach the event } +async function openMessagePopup(message: string) { + + + const modalmessage = document.getElementById("modal-message") ?? null; + if(!message) return + const obj:any = JSON.parse(message); + if (modalmessage) + modalmessage.innerHTML = ` +
+
+
Next Game Message: ${obj.link}
+
`; + const gameMessage = document.getElementById("game-modal") ?? null; + if (gameMessage) + gameMessage.classList.remove("hidden"); + // The popup now exists → attach the event +} + + + function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn { @@ -470,7 +493,7 @@ function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn socket.on('profilMessage', (profil: ClientProfil) => { openProfilePopup(profil); - actionBtnPopUpClear(profil); + actionBtnPopUpClear(profil, socket); actionBtnPopUpInvite(profil, socket); }); @@ -489,37 +512,39 @@ function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn addMessage(message); }) - type Providers = { - name: string, - display_name: string, - icon_url?: string, - color?: { default: string, hover: string }, - }; + //receives broadcast of the next GAME + socket.on('nextGame', (message) => { + openMessagePopup(message); + // addMessage(message); + }) let toggle = false - window.addEventListener("focus", () => { + window.addEventListener("focus", async () => { //nst bwhoami = document.getElementById('b-whoami') as HTMLButtonElement; - if (window.location.pathname === '/app/chat') { + + setTimeout(() => { connected(socket); - console.log("%cWindow is focused on /chat:" + socket.id, color.green); + }, 0); + if (window.location.pathname === '/app/chat') { + console.log('%cWindow is focused on /chat:' + socket.id, color.green); if (socket.id) { - windowStateVisable(); + await windowStateVisable(); } toggle = true; } }); window.addEventListener("blur", () => { - console.log("%cWindow is not focused on /chat", color.red); + console.log('%cWindow is not focused on /chat', color.red); if (socket.id) windowStateHidden(); toggle = false; }); - // setInterval(async () => { // //connected(socket); - // },10000); // every 10 seco + // },10000); // every 10 sec + socket.on('listBud', async (myBuddies: string) => { const buddies = document.getElementById('div-buddies') as HTMLDivElement; console.log('List buddies connected ', myBuddies); @@ -552,6 +577,7 @@ function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn const buddies = document.getElementById('div-buddies') as HTMLDivElement; const bquit = document.getElementById('b-quit') as HTMLDivElement; const systemWindow = document.getElementById('system-box') as HTMLDivElement; + const bnextGame = document.getElementById('b-nextGame') as HTMLDivElement; chatWindow.textContent = ''; chatWindow.innerHTML = ''; @@ -578,6 +604,18 @@ function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn if (profilList) profilList.classList.add("hidden"); }); + + + + const buttonMessage = document.getElementById("close-modal-message") ?? null; + + if (buttonMessage) + buttonMessage.addEventListener("click", () => { + const gameMessage = document.getElementById("game-modal") ?? null; + if (gameMessage) gameMessage.classList.add("hidden"); + }); + + // Send button sendButton?.addEventListener("click", () => { if (sendtextbox && sendtextbox.value.trim()) { @@ -631,6 +669,14 @@ function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn if (chatWindow) { chatWindow.innerHTML = ''; } + clear(socket); //DEV testing broadcastGames + }); + + // Dev Game message button + bnextGame?.addEventListener("click", () => { + if (chatWindow) { + socket.emit('nextGame'); + } }); bquit?.addEventListener('click', () => { @@ -652,5 +698,4 @@ function handleChat(_url: string, _args: RouteHandlerParams): RouteHandlerReturn } } }; -addRoute('/chat', handleChat, { bypass_auth: true }); - +addRoute('/chat', handleChat, { bypass_auth: true }); \ No newline at end of file diff --git a/src/@shared/src/utils/index.ts b/src/@shared/src/utils/index.ts index a79cbe9..96d02ad 100644 --- a/src/@shared/src/utils/index.ts +++ b/src/@shared/src/utils/index.ts @@ -142,3 +142,11 @@ export function typeResponse( export function isNullish(v: T | undefined | null): v is null | undefined { return v === null || v === undefined; } + +/** +/* EXPERIMENTAL: how to send a starting game link to chat +**/ +export async function sendGameLinkToChatService(link: string) :Promise { + const payload = { link }; + return JSON.stringify(payload); +} \ No newline at end of file diff --git a/src/chat/src/app.ts b/src/chat/src/app.ts index 14258e2..e904b15 100644 --- a/src/chat/src/app.ts +++ b/src/chat/src/app.ts @@ -7,6 +7,7 @@ import * as swagger from '@shared/swagger'; import * as utils from '@shared/utils'; import { Server, Socket } from 'socket.io'; import type { User } from '@shared/database/mixin/user'; +import { sendGameLinkToChatService } from '../../@shared/src/utils/index'; // colors for console.log export const color = { @@ -46,7 +47,7 @@ export type ClientProfil = { command: string, destination: string, type: string, - user: string, + user: string, loginName: string, userID: string, text: string, @@ -55,21 +56,28 @@ export type ClientProfil = { SenderName: string, innerHtml?: string, -}; +}; +/** +/* TODO find the description info for profil / or profil game link and return +**/ +function createNextGame() { + return 'The next Game is Starting click here to watch'; +}; -// export type inviteGame = { -// command?: string, -// destination?: string, -// type?: string, -// user?: string, -// loginName?: string, -// userID?: string, -// innerHtml?: string, -// timestamp?: number, -// SenderWindowID?:string, -// SenderName: string -// }; +function setAboutPlayer(about: string): string { + if (!about) { + about = 'Player is good Shape - This is a default description'; + } + return about; +}; + +function setGameLink(link: string): string { + if (!link) { + link = 'Click me'; + } + return link; +}; const clientChat = new Map(); @@ -118,6 +126,7 @@ declare module 'fastify' { profilMessage: (data: ClientProfil) => void; inviteGame: (data: ClientProfil) => void; privMessageCopy: (msg: string) => void; + nextGame: (msg: string) => void; message: (msg: string) => void; listBud: (msg: string) => void; testend: (sock_id_client: string) => void; @@ -189,6 +198,28 @@ async function onReady(fastify: FastifyInstance) { }); } + + async function broadcastNextGame(gameLink?: Promise) { + + const link = gameLink ? await gameLink : undefined; + const sockets = await fastify.io.fetchSockets(); + // fastify.io.fetchSockets().then((sockets) => { + for (const socket of sockets) { + // Skip sender's own socket + const clientInfo = clientChat.get(socket.id); + if (!clientInfo?.user) { + console.log(color.yellow, `Skipping socket ${socket.id} (no user found)`); + continue; + } + // Emit structured JSON object + if (link) { + socket.emit('nextGame', link); + } + // Debug logs + // console.log(color.green, `'DEBUG LOG: Broadcast to:', ${data.command} message: ${data.text}`); + } + }; + // function formatTimestamp(ms: number) { // const d = new Date(ms); // return d.toLocaleString('fr-FR', { timeZone: 'Europe/Paris' }); @@ -198,21 +229,9 @@ async function onReady(fastify: FastifyInstance) { return users.find(user => user.name === name) || null; } - ///TODO find the description info for profil / or profil game link and return - function getAboutPlayer( ): string{ - const description = 'Player is good Shape this needs to be replaced by a bd.function()'; - return description; - } - - function getGameLink(): string{ - const link = `Click me`; - return link; - } - - // this function returns html the profil pop up in CHAT of a user 'nickname unique' TODO .... async function getProfil(user: string, socket: Socket): Promise { - + let clientProfil!: ClientProfil; const users: User[] = fastify.db.getAllUsers() ?? []; const allUsers: User | null = getUserByName(users, user); @@ -220,20 +239,20 @@ async function onReady(fastify: FastifyInstance) { if (user === allUsers?.name) { console.log(color.yellow, `'login Name: '${allUsers.login}' user: '${user}'`); - clientProfil = + clientProfil = { command: 'getProfil', destination: 'profilMsg', type: 'chat' as const, - user: `${allUsers.name}`, + user: `${allUsers.name}`, loginName: `${allUsers?.login ?? 'Guest'}`, userID: `${allUsers?.id ?? ''}`, - text: getAboutPlayer(), + text: setAboutPlayer(''), timestamp: Date.now(), SenderWindowID: socket.id, SenderName: '', innerHtml: '', - }; + }; } return clientProfil; }; @@ -250,10 +269,10 @@ async function onReady(fastify: FastifyInstance) { function sendInvite(innerHtml: string, data: ClientProfil) { fastify.io.fetchSockets().then((sockets) => { - + let targetSocket; for (const socket of sockets) { - let clientInfo: string = clientChat.get(socket.id)?.user || ''; + const clientInfo: string = clientChat.get(socket.id)?.user || ''; if (clientInfo === data.user) { console.log(color.yellow, 'FOUND:', data.user); targetSocket = socket || ''; @@ -261,7 +280,7 @@ async function onReady(fastify: FastifyInstance) { } } data.innerHtml = innerHtml ?? ''; - if (targetSocket) { + if (targetSocket) { targetSocket.emit('inviteGame', data); } }); @@ -333,6 +352,13 @@ async function onReady(fastify: FastifyInstance) { console.log('testend received from client socket id:', sock_id_cl); }); + + socket.on('nextGame', () => { + const link = createNextGame(); + const game: Promise = sendGameLinkToChatService(link); + broadcastNextGame(game); + }); + socket.on('list', (object) => { const userFromFrontend = object || null; @@ -496,8 +522,8 @@ async function onReady(fastify: FastifyInstance) { const clientName: string = clientChat.get(socket.id)?.user || ''; const profilInvite: ClientProfil = JSON.parse(data) || ''; // const users: User[] = fastify.db.getAllUsers() ?? []; - - const inviteHtml: string = `invites you to a game ` + getGameLink(); + + const inviteHtml: string = 'invites you to a game ' + setGameLink(''); if (clientName !== null) { // const testuser: User | null = getUserByName(users, profilInvite.user ?? ''); // console.log(color.yellow, 'user:', testuser?.name ?? 'Guest');