diff --git a/frontend/index.html b/frontend/index.html index 1257854..f5da4a5 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -34,13 +34,14 @@ 🏠 Home 👤 Login 👤 Signin - 👤 Chat ⭕ Tic-Tac-Toe ▮•▮ Ping Pong ⚙️ Settings 🚪 Logout +
+ @@ -51,12 +52,14 @@
+ + diff --git a/frontend/src/pages/chat/chat.css b/frontend/src/chat/chat.css similarity index 94% rename from frontend/src/pages/chat/chat.css rename to frontend/src/chat/chat.css index 9e27632..9b4b0f1 100644 --- a/frontend/src/pages/chat/chat.css +++ b/frontend/src/chat/chat.css @@ -282,6 +282,22 @@ div-private { items-center; } +.chat-button { + @apply + z-100 + text-3xl + fixed bottom-6 + right-6 + w-14 + h-14 + rounded-full + bg-gray-600 + text-white + shadow-lg + flex items-center + justify-center + hover:bg-red-700 +} diff --git a/frontend/src/chat/chat.html b/frontend/src/chat/chat.html new file mode 100644 index 0000000..e4601d3 --- /dev/null +++ b/frontend/src/chat/chat.html @@ -0,0 +1,53 @@ +
+
+

+ Chatter Box +


+ + + +
System: connecting ...
+
+ + +
+ +
+
+
+ +
🔕
+
💔
+ +
+
+ +
+

Ping Buddies

+
+
+
+
+ + +
+
+
+
+
+ + + + diff --git a/frontend/src/chat/chat.ts b/frontend/src/chat/chat.ts new file mode 100644 index 0000000..d6ab56d --- /dev/null +++ b/frontend/src/chat/chat.ts @@ -0,0 +1,420 @@ +import "./chat.css"; +import io, { Socket } from "socket.io-client"; +import type { blockedUnBlocked } from "./types_front"; +import type { + ClientMessage, + ClientProfil, + ClientProfilPartial, +} from "./types_front"; +import type { User } from "@app/auth"; +import { + addRoute, + setTitle, + type RouteHandlerParams, + type RouteHandlerReturn, +} from "@app/routing"; +import authHtml from "./chat.html?raw"; +import { getUser } from "@app/auth"; +import { listBuddies } from "./chatHelperFunctions/listBuddies"; +import { getProfil } from "./chatHelperFunctions/getProfil"; +import { addMessage } from "./chatHelperFunctions/addMessage"; +import { broadcastMsg } from "./chatHelperFunctions/broadcastMsg"; +import { openProfilePopup } from "./chatHelperFunctions/openProfilePopup"; +import { actionBtnPopUpBlock } from "./chatHelperFunctions/actionBtnPopUpBlock"; +import { windowStateHidden } from "./chatHelperFunctions/windowStateHidden"; +import { blockUser } from "./chatHelperFunctions/blockUser"; +import { parseCmdMsg } from "./chatHelperFunctions/parseCmdMsg"; +import { actionBtnPopUpInvite } from "./chatHelperFunctions/actionBtnPopUpInvite"; +import { waitSocketConnected } from "./chatHelperFunctions/waitSocketConnected"; +import { connected } from "./chatHelperFunctions/connected"; +import { quitChat } from "./chatHelperFunctions/quitChat"; +import { openMessagePopup } from "./chatHelperFunctions/openMessagePopup"; +import { windowStateVisable } from "./chatHelperFunctions/windowStateVisable"; +import { cmdList } from "./chatHelperFunctions/cmdList"; +import { showInfo } from '../toast'; + +const MAX_SYSTEM_MESSAGES = 10; +let inviteMsgFlag: boolean = false; +export let noGuestFlag: boolean = true; + +declare module "ft_state" { + interface State { + chatSock?: Socket; + } +} + +export function getSocket(): Socket { + if (window.__state.chatSock === undefined) + window.__state.chatSock = io(window.location.host, { + path: "/api/chat/socket.io/", + }) as any as Socket; + return window.__state.chatSock; +} + +const chatBox = document.getElementById("chatBox")!; +chatBox.classList.add('hidden'); +chatBox.innerHTML = authHtml; + +let socket = getSocket(); +let blockMessage: boolean; +// Listen for the 'connect' event +socket.on("connect", async () => { + const systemWindow = document.getElementById("system-box") as HTMLDivElement; + const sendtextbox = document.getElementById( + "t-chat-window" + ) as HTMLButtonElement; + const noGuest = document.getElementById("noGuest") ?? null; + + await waitSocketConnected(socket); + const user = getUser()?.name; + const userID = getUser()?.id; + // Ensure we have a user AND socket is connected + if (!user || !socket.connected || !noGuest) return; + const message = { + command: "", + destination: "system-info", + type: "chat", + user, + token: document.cookie ?? "", + text: " has Just ARRIVED in the chat", + timestamp: Date.now(), + SenderWindowID: socket.id, + SenderID: userID, + }; + socket.emit("message", JSON.stringify(message)); + const guest = getUser()?.guest; + if (guest) { + noGuest.innerText = ""; + } else { + noGuest.innerText = "❤️"; + } + + const userProfile: ClientProfil = { + command: "@noguest", + destination: "", + type: "chat", + timestamp: Date.now(), + guestmsg: true, + }; + socket.emit("guestmsg", JSON.stringify(userProfile)); + const messageElement = document.createElement("div"); + messageElement.textContent = `${user}: is connected au server`; + systemWindow.appendChild(messageElement); + systemWindow.scrollTop = systemWindow.scrollHeight; +}); + +// Listen for messages from the server "MsgObjectServer" +socket.on("MsgObjectServer", (data: { message: ClientMessage }) => { + const systemWindow = document.getElementById("system-box") as HTMLDivElement; + const chatWindow = document.getElementById("t-chatbox") as HTMLDivElement; + + if (socket) { + connected(socket); + } + + if (chatWindow && data.message.destination === "") { + const messageElement = document.createElement("div"); + messageElement.textContent = `${data.message.user}: ${data.message.text}`; + chatWindow.appendChild(messageElement); + chatWindow.scrollTop = chatWindow.scrollHeight; + } + + if (chatWindow && data.message.destination === "privateMsg") { + const messageElement = document.createElement("div-private"); + messageElement.textContent = `🔒${data.message.user}: ${data.message.text}`; + chatWindow.appendChild(messageElement); + chatWindow.scrollTop = chatWindow.scrollHeight; + } + + if (chatWindow && data.message.destination === "inviteMsg") { + const messageElement = document.createElement("div-private"); + const chatWindow = document.getElementById("t-chatbox") as HTMLDivElement; + messageElement.innerHTML = `🏓${data.message.SenderUserName}: ${data.message.innerHtml}`; + chatWindow.appendChild(messageElement); + chatWindow.scrollTop = chatWindow.scrollHeight; + } + + if (systemWindow && data.message.destination === "system-info") { + const messageElement = document.createElement("div"); + messageElement.textContent = `${data.message.user}: ${data.message.text}`; + systemWindow.appendChild(messageElement); + + // keep only last 10 + while (systemWindow.children.length > MAX_SYSTEM_MESSAGES) { + systemWindow.removeChild(systemWindow.firstChild!); + } + systemWindow.scrollTop = systemWindow.scrollHeight; + } +}); + +socket.on("profilMessage", (profil: ClientProfil) => { + profil.SenderID = getUser()?.id ?? ""; + profil.SenderName = getUser()?.name ?? ""; + openProfilePopup(profil); + socket.emit("isBlockdBtn", profil); + socket.emit("check_Block_button", profil); + actionBtnPopUpInvite(profil, socket); + actionBtnPopUpBlock(profil, socket); +}); + +socket.on("blockUser", (blocked: ClientProfil) => { + let icon = "⛔"; + if (inviteMsgFlag) { + const chatWindow = document.getElementById("t-chatbox") as HTMLDivElement; + const messageElement = document.createElement("div"); + if (`${blocked.text}` === "I have un-blocked you") { + icon = "💚"; + } + messageElement.innerText = `${icon}${blocked.SenderName}: ${blocked.text}`; + chatWindow.appendChild(messageElement); + chatWindow.scrollTop = chatWindow.scrollHeight; + } +}); + +socket.on("blockBtn", (data: blockedUnBlocked) => { + const blockUserBtn = document.querySelector("#popup-b-block"); + if (blockUserBtn) { + let message = ""; + if (data.userState === "block") { + (message = "un-block"), (blockMessage = true); + } else { + (message = "block"), (blockMessage = false); + } + blockUserBtn.textContent = message; + } +}); + +socket.on("logout", () => { + quitChat(socket); +}); + +socket.on("privMessageCopy", (message: string) => { + addMessage(message); +}); + +//receives broadcast of the next GAME +socket.on("nextGame", (message: string) => { + openMessagePopup(message); +}); + +let toggle = false; +window.addEventListener("focus", async () => { + setTimeout(() => { + connected(socket); + }, 16); + if (window.location.pathname === "/app/chat") { + if (socket.id) { + await windowStateVisable(); + } + toggle = true; + } +}); + +window.addEventListener("blur", () => { + if (socket.id) windowStateHidden(); + toggle = false; +}); + +socket.on("listBud", async (myBuddies: string[]) => { + const buddies = document.getElementById("div-buddies") as HTMLDivElement; + listBuddies(socket, buddies, myBuddies); +}); + +socket.once("welcome", (data) => { + const buddies = document.getElementById("div-buddies") as HTMLDivElement; + buddies.textContent = ""; + buddies.innerHTML = ""; + connected(socket); + addMessage(`${data.msg} ` + getUser()?.name); +}); +setTitle("Chat Page"); +const sendButton = document.getElementById("b-send") as HTMLButtonElement; +const chatWindow = document.getElementById("t-chatbox") as HTMLDivElement; +const sendtextbox = document.getElementById( + "t-chat-window" +) as HTMLButtonElement; +const clearText = document.getElementById("b-clear") as HTMLButtonElement; +const buddies = document.getElementById("div-buddies") as HTMLDivElement; +const bquit = document.getElementById("b-quit") as HTMLDivElement; + +buddies.textContent = ""; +buddies.innerHTML = ""; +const buttonPro = document.getElementById("close-modal") ?? null; + +if (buttonPro) + buttonPro.addEventListener("click", () => { + const profilList = document.getElementById("profile-modal") ?? null; + 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"); + const modalmessage = document.getElementById("modal-message") ?? null; + if (modalmessage) { + modalmessage.innerHTML = ""; + } + }); + +// Send button +sendButton?.addEventListener("click", () => { + const notify = document.getElementById("notify") ?? null; + const noGuest = document.getElementById("noGuest") ?? null; + const userId = getUser()?.id; + const userAskingToBlock = getUser()?.name; + if (sendtextbox && sendtextbox.value.trim()) { + let msgText: string = sendtextbox.value.trim(); + const msgCommand = parseCmdMsg(msgText) ?? ""; + connected(socket); + if (msgCommand !== "") { + switch (msgCommand[0]) { + case "@msg": + broadcastMsg(socket, msgCommand); + break; + + case "@block": + if (msgCommand[1] === "") { + break; + } + if (!userAskingToBlock) return; + if (!userId) return; + const userToBlock: ClientProfil = { + command: msgCommand[0], + destination: "", + type: "chat", + user: msgCommand[1], + userID: userId, + timestamp: Date.now(), + SenderWindowID: socket.id, + SenderName: userAskingToBlock, + }; + blockUser(userToBlock, socket); + break; + + case "@notify": + if (notify === null) { + break; + } + if (inviteMsgFlag === false) { + notify.innerText = "🔔"; + inviteMsgFlag = true; + } else { + notify.innerText = "🔕"; + inviteMsgFlag = false; + } + break; + + case "@guest": + if (!userId) { + return; + } + if (!userAskingToBlock) { + return; + } + if (noGuest === null) { + break; + } + const guest = getUser()?.guest; + if (noGuestFlag === false && noGuest.innerText === "💔") { + noGuest.innerText = "❤️​"; + noGuestFlag = true; + } else { + noGuest.innerText = "💔"; + noGuestFlag = false; + } + if (guest) { + noGuestFlag = true; + noGuest.innerText = ""; + sendtextbox.value = ""; + } + const userProfile: ClientProfilPartial = { + command: "@noguest", + destination: "", + type: "chat", + user: userAskingToBlock, + userID: userId, + timestamp: Date.now(), + SenderWindowID: "", + guestmsg: noGuestFlag, + }; + socket.emit("guestmsg", JSON.stringify(userProfile)); + break; + + case "@profile": + if (msgCommand[1] === "") { + break; + } + getProfil(socket, msgCommand[1]); + break; + case "@cls": + chatWindow.innerHTML = ""; + break; + case "@help": + cmdList(); + break; + + case "@quit": + quitChat(socket); + break; + + default: + const user: User | null = getUser(); + if (!user) return; + if (!user || !socket.connected) return; + const message: ClientProfilPartial = { + command: msgCommand[0], + destination: "", + type: "chat", + user: user.name, + userID: user.id, + token: document.cookie ?? "", + text: msgCommand[1], + timestamp: Date.now(), + SenderWindowID: socket.id ?? "", + SenderID: user.id, + }; + socket.emit("privMessage", JSON.stringify(message)); + break; + } + // Clear the input in all cases + sendtextbox.value = ""; + } + } +}); + +// Clear Text button +clearText?.addEventListener("click", () => { + if (chatWindow) { + chatWindow.innerHTML = ""; + } +}); + +bquit?.addEventListener("click", () => { + showInfo('Nigel close the chat overlay please') +}); + +// Enter key to send message +sendtextbox.addEventListener("keydown", (event) => { + if (!sendtextbox) return; + if (event.key === "Enter") { + event.preventDefault(); + sendButton?.click(); + } +}); + +const chatButton = document.querySelector('#chatButton'); +chatButton!.addEventListener("click", () => { + + const overlay = document.querySelector('#overlay')!; + if (chatBox.classList.contains('hidden')) { + chatBox.classList.toggle('hidden'); + overlay.classList.add('opacity-60'); + } else { + chatBox.classList.toggle('hidden'); + overlay.classList.remove('opacity-60'); + } +}); + diff --git a/frontend/src/pages/chat/chatHelperFunctions/actionBtnPopUpBlock.ts b/frontend/src/chat/chatHelperFunctions/actionBtnPopUpBlock.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/actionBtnPopUpBlock.ts rename to frontend/src/chat/chatHelperFunctions/actionBtnPopUpBlock.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/actionBtnPopUpInvite.ts b/frontend/src/chat/chatHelperFunctions/actionBtnPopUpInvite.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/actionBtnPopUpInvite.ts rename to frontend/src/chat/chatHelperFunctions/actionBtnPopUpInvite.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/addMessage.ts b/frontend/src/chat/chatHelperFunctions/addMessage.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/addMessage.ts rename to frontend/src/chat/chatHelperFunctions/addMessage.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/blockUser.ts b/frontend/src/chat/chatHelperFunctions/blockUser.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/blockUser.ts rename to frontend/src/chat/chatHelperFunctions/blockUser.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/broadcastMsg.ts b/frontend/src/chat/chatHelperFunctions/broadcastMsg.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/broadcastMsg.ts rename to frontend/src/chat/chatHelperFunctions/broadcastMsg.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/clearChatWindow.ts b/frontend/src/chat/chatHelperFunctions/clearChatWindow.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/clearChatWindow.ts rename to frontend/src/chat/chatHelperFunctions/clearChatWindow.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/cmdList.ts b/frontend/src/chat/chatHelperFunctions/cmdList.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/cmdList.ts rename to frontend/src/chat/chatHelperFunctions/cmdList.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/connected.ts b/frontend/src/chat/chatHelperFunctions/connected.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/connected.ts rename to frontend/src/chat/chatHelperFunctions/connected.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/getProfil.ts b/frontend/src/chat/chatHelperFunctions/getProfil.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/getProfil.ts rename to frontend/src/chat/chatHelperFunctions/getProfil.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/incrementCounter.ts b/frontend/src/chat/chatHelperFunctions/incrementCounter.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/incrementCounter.ts rename to frontend/src/chat/chatHelperFunctions/incrementCounter.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/inviteToPlayPong.ts b/frontend/src/chat/chatHelperFunctions/inviteToPlayPong.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/inviteToPlayPong.ts rename to frontend/src/chat/chatHelperFunctions/inviteToPlayPong.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/isLoggedIn.ts b/frontend/src/chat/chatHelperFunctions/isLoggedIn.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/isLoggedIn.ts rename to frontend/src/chat/chatHelperFunctions/isLoggedIn.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/listBuddies.ts b/frontend/src/chat/chatHelperFunctions/listBuddies.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/listBuddies.ts rename to frontend/src/chat/chatHelperFunctions/listBuddies.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/logout.ts b/frontend/src/chat/chatHelperFunctions/logout.ts similarity index 71% rename from frontend/src/pages/chat/chatHelperFunctions/logout.ts rename to frontend/src/chat/chatHelperFunctions/logout.ts index 9e0d9bc..1aeadfc 100644 --- a/frontend/src/pages/chat/chatHelperFunctions/logout.ts +++ b/frontend/src/chat/chatHelperFunctions/logout.ts @@ -1,11 +1,10 @@ import { Socket } from "socket.io-client"; -import { __socket } from "../chat"; export function logout(socket: Socket) { socket.emit("logout"); // notify server socket.disconnect(); // actually close the socket localStorage.clear(); - if (__socket !== undefined) - __socket.close(); + if (window.__state.chatSock !== undefined) + window.__state.chatSock.close(); }; diff --git a/frontend/src/pages/chat/chatHelperFunctions/openMessagePopup.ts b/frontend/src/chat/chatHelperFunctions/openMessagePopup.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/openMessagePopup.ts rename to frontend/src/chat/chatHelperFunctions/openMessagePopup.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/openProfilePopup.ts b/frontend/src/chat/chatHelperFunctions/openProfilePopup.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/openProfilePopup.ts rename to frontend/src/chat/chatHelperFunctions/openProfilePopup.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/parseCmdMsg.ts b/frontend/src/chat/chatHelperFunctions/parseCmdMsg.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/parseCmdMsg.ts rename to frontend/src/chat/chatHelperFunctions/parseCmdMsg.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/quitChat.ts b/frontend/src/chat/chatHelperFunctions/quitChat.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/quitChat.ts rename to frontend/src/chat/chatHelperFunctions/quitChat.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/setGuestInfo.ts b/frontend/src/chat/chatHelperFunctions/setGuestInfo.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/setGuestInfo.ts rename to frontend/src/chat/chatHelperFunctions/setGuestInfo.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/waitSocketConnected.ts b/frontend/src/chat/chatHelperFunctions/waitSocketConnected.ts similarity index 100% rename from frontend/src/pages/chat/chatHelperFunctions/waitSocketConnected.ts rename to frontend/src/chat/chatHelperFunctions/waitSocketConnected.ts diff --git a/frontend/src/pages/chat/chatHelperFunctions/windowStateHidden.ts b/frontend/src/chat/chatHelperFunctions/windowStateHidden.ts similarity index 85% rename from frontend/src/pages/chat/chatHelperFunctions/windowStateHidden.ts rename to frontend/src/chat/chatHelperFunctions/windowStateHidden.ts index a38ae54..27d45f9 100644 --- a/frontend/src/pages/chat/chatHelperFunctions/windowStateHidden.ts +++ b/frontend/src/chat/chatHelperFunctions/windowStateHidden.ts @@ -1,8 +1,7 @@ -import { __socket } from '../chat'; import { updateUser } from "@app/auth"; export async function windowStateHidden() { - const socketId = __socket || undefined; + const socketId = window.__state.chatSock || undefined; // let oldName = localStorage.getItem("oldName") ?? undefined; let oldName: string; if (socketId === undefined) return; diff --git a/frontend/src/pages/chat/chatHelperFunctions/windowStateVisable.ts b/frontend/src/chat/chatHelperFunctions/windowStateVisable.ts similarity index 89% rename from frontend/src/pages/chat/chatHelperFunctions/windowStateVisable.ts rename to frontend/src/chat/chatHelperFunctions/windowStateVisable.ts index ed5108f..6ff315b 100644 --- a/frontend/src/pages/chat/chatHelperFunctions/windowStateVisable.ts +++ b/frontend/src/chat/chatHelperFunctions/windowStateVisable.ts @@ -1,4 +1,3 @@ -import { __socket } from "../chat"; import { setTitle } from "@app/routing"; import { updateUser } from "@app/auth"; @@ -11,7 +10,7 @@ import { updateUser } from "@app/auth"; export async function windowStateVisable() { const buddies = document.getElementById('div-buddies') as HTMLDivElement; - const socketId = __socket || undefined; + const socketId = window.__state.chatSock || undefined; let oldName = localStorage.getItem("oldName") || undefined; if (socketId === undefined || oldName === undefined) {return;}; diff --git a/frontend/src/pages/chat/types_front.ts b/frontend/src/chat/types_front.ts similarity index 100% rename from frontend/src/pages/chat/types_front.ts rename to frontend/src/chat/types_front.ts diff --git a/frontend/src/pages/index.ts b/frontend/src/pages/index.ts index ec82683..4a5e931 100644 --- a/frontend/src/pages/index.ts +++ b/frontend/src/pages/index.ts @@ -1,6 +1,6 @@ import { setTitle, handleRoute } from '@app/routing'; import './root/root.ts' -import './chat/chat.ts' +import '../chat/chat.ts' import './pong/pong.ts' import './login/login.ts' import './signin/signin.ts' diff --git a/frontend/src/pages/pong/pong.css b/frontend/src/pages/pong/pong.css index adfb9c6..0be18a5 100644 --- a/frontend/src/pages/pong/pong.css +++ b/frontend/src/pages/pong/pong.css @@ -6,38 +6,147 @@ @tailwind utilities; -@layer utilities { - .gray-color { - @apply border-gray-500 bg-gray-500 - } - .white-color { - @apply border-white bg-white - } - .fit-all { - @apply - w-fit h-fit - } - .blue-hover { - @apply - hover:bg-blue-200 - hover:border-blue-200 - } - .rounded-elem { - @apply - border-6 rounded-3xl - } - .circle-8 { - @apply w-8 h-8 rounded-full - } - .base-box { - @apply - flex items-center justify-center - } - .focus-elem { - @apply - z-50 - shadow-2xl - text-center +.btn-style { + @apply + w-25 + h-8 + border + border-gray-500 + rounded-3xl + bg-gray-500 + text-white + cursor-pointer + shadow-[0_2px_0_0_black] + transition-all + hover:bg-blue-200 + active:bg-gray-400 + active:translate-y-px + active:shadow-[0_2px_0_0_black]; +} + +.chatbox-style { + @apply + w-162.5 + h-75 /* increase height if needed */ + p-2 + border + border-black + shadow-2xl + text-left + text-gray-700 + bg-white + rounded-3xl + overflow-y-auto + whitespace-pre-line + flex + flex-col + mx-auto; +} + +.system-info { + @apply + h-10 + bg-gray-200 + text-gray-700 + p-3 + rounded-3xl + mb-2 border + border-gray-200 + text-center + shadow + overflow-y-auto + justify-end /* 👈 forces text to bottom */ + relative; /* needed for overlay */ +} + +.displaybox { + @apply + fixed + inset-0 + flex + items-center + justify-center + bg-[#43536b]; + +} + +.mainboxDisplay { + @apply + fixed + top-1/2 + left-1/2 + -translate-x-1/2 + -translate-y-1/2 + bg-gray-200 w-212.5 + p-6 rounded-xl + shadow-2xl + text-center + z-50; +} + +.mainboxDisplay button { + @apply + cursor-pointer +} + +.pongbox-style { + @apply + h-112.5 + w-200 + bg-gray-400 + text-6xl + flex + items-center + justify-center; +} + +.text-style { + @apply + text-black + items-center + justify-center + min-w-[2rem] h-8 px-2 + rounded-md border border-gray-300 + bg-gray-100 text-gray-800 + font-mono text-sm font-medium + shadow-sm + select-none +} + + +.pong-field { + @apply relative w-200 h-112.5 bg-black; +} + +.pong-bat { + @apply absolute w-3 h-20 bg-white; +} + +.pong-batleft { + @apply absolute left-4 w-3 h-20 top-0; +} + +.pong-batright { + @apply absolute right-4 w-3 h-20 top-0; +} + +.pong-center-line { + @apply + absolute + left-1/2 + top-0 + h-full + w-1 + -translate-x-1/2 + bg-[linear-gradient(to_bottom,white_50%,transparent_50%)] + bg-size-[4px_20px]; +} + +.pong-end-screen { + @apply + rounded-2xl + absolute + justify-center text-black absolute text-xl @@ -115,3 +224,36 @@ absolute right-4 top-0; } } + +.pong-protips-key { + @apply + inline-flex + items-center + justify-center + min-w-[2rem] h-8 px-2 + rounded-md border border-gray-300 + bg-gray-100 text-gray-800 + font-mono text-sm font-medium + shadow-sm + select-none +} + +.pong-how-to-play { + @apply + inline-flex items-center justify-center + rounded-full w-8 h-8 bg-blue-500 + border-10 border-blue-500 +} + +.chatPopUp { + @apply + fixed + inset-0 + flex + justify-center + items-center; +} + +.hidden{ + display: none; +} diff --git a/frontend/src/pages/pong/pong.ts b/frontend/src/pages/pong/pong.ts index 7bf44fb..5f0e07d 100644 --- a/frontend/src/pages/pong/pong.ts +++ b/frontend/src/pages/pong/pong.ts @@ -125,6 +125,7 @@ function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn navigateTo("/app"); return; } + if ( !batLeft || !batRight || @@ -142,7 +143,8 @@ function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn !tour_infos ) // sanity check - return showError("fatal error"); + return showError("fatal error"); 👤 Chat + if (!how_to_play_btn || !protips) showError("missing protips"); // not a fatal error tournamentBtn.addEventListener("click", () => { @@ -179,6 +181,16 @@ function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn how_to_play_btn.innerText = how_to_play_btn.innerText === "?" ? "x" : "?"; }); + } + + document.addEventListener("keydown", (e) => {keys[e.key.toLowerCase()] = true;}); + document.addEventListener("keyup", (e) => {keys[e.key.toLowerCase()] = false;}); + + setInterval(() => { // key sender + if (keys['escape'] === true && protips && how_to_play_btn) { + protips.classList.add("hidden"); + how_to_play_btn.innerText = '?'; + } document.addEventListener("keydown", (e) => { keys[e.key.toLowerCase()] = true; @@ -324,6 +336,7 @@ function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn queueBtn.innerText = QueueState.InQueu; socket.emit("enqueue"); }); + LocalGameBtn.addEventListener("click", () => { if ( queueBtn.innerText !== QueueState.Iddle || diff --git a/frontend/src/pages/root/pong_box_image.png b/frontend/src/pages/root/pong_box_image.png deleted file mode 100644 index b9a870e..0000000 Binary files a/frontend/src/pages/root/pong_box_image.png and /dev/null differ diff --git a/frontend/src/pages/root/root.html b/frontend/src/pages/root/root.html index 379444b..7d16696 100644 --- a/frontend/src/pages/root/root.html +++ b/frontend/src/pages/root/root.html @@ -101,6 +101,7 @@
+

Embrace the Ball Lifestyle