Chat moved up to top level now in all services frontend
This commit is contained in:
parent
814c389e38
commit
b4af6e08ca
32 changed files with 687 additions and 42 deletions
|
|
@ -34,13 +34,14 @@
|
||||||
<a href="/" class="hover:bg-gray-700 rounded-md px-3 py-2">🏠 Home</a>
|
<a href="/" class="hover:bg-gray-700 rounded-md px-3 py-2">🏠 Home</a>
|
||||||
<a href="/login" class="hover:bg-gray-700 rounded-md px-3 py-2">👤 Login</a>
|
<a href="/login" class="hover:bg-gray-700 rounded-md px-3 py-2">👤 Login</a>
|
||||||
<a href="/signin" class="hover:bg-gray-700 rounded-md px-3 py-2">👤 Signin</a>
|
<a href="/signin" class="hover:bg-gray-700 rounded-md px-3 py-2">👤 Signin</a>
|
||||||
<a href="/chat" class="hover:bg-gray-700 rounded-md px-3 py-2">👤 Chat</a>
|
|
||||||
<a href="/ttt" class="hover:bg-gray-700 rounded-md px-3 py-2">⭕ Tic-Tac-Toe</a>
|
<a href="/ttt" class="hover:bg-gray-700 rounded-md px-3 py-2">⭕ Tic-Tac-Toe</a>
|
||||||
<a href="/pong" class="hover:bg-gray-700 rounded-md px-3 py-2">▮•▮ Ping Pong</a>
|
<a href="/pong" class="hover:bg-gray-700 rounded-md px-3 py-2">▮•▮ Ping Pong</a>
|
||||||
<a href="/contact" class="hover:bg-gray-700 rounded-md px-3 py-2">⚙️ Settings</a>
|
<a href="/contact" class="hover:bg-gray-700 rounded-md px-3 py-2">⚙️ Settings</a>
|
||||||
<a href="/logout" class="hover:bg-gray-700 rounded-md px-3 py-2">🚪 Logout</a>
|
<a href="/logout" class="hover:bg-gray-700 rounded-md px-3 py-2">🚪 Logout</a>
|
||||||
</nav>
|
</nav>
|
||||||
</aside>
|
</aside>
|
||||||
|
<div id="chatBox"> </div>
|
||||||
|
|
||||||
<div class="fixed top-0 left-0 opacity-40" hidden>
|
<div class="fixed top-0 left-0 opacity-40" hidden>
|
||||||
<!-- >this is used so tailwind create the class styles... -->
|
<!-- >this is used so tailwind create the class styles... -->
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -51,12 +52,14 @@
|
||||||
<!-- Main content -->
|
<!-- Main content -->
|
||||||
<main class="pt-16 px-6 pb-8 w-full h-full container" id="app">
|
<main class="pt-16 px-6 pb-8 w-full h-full container" id="app">
|
||||||
</main>
|
</main>
|
||||||
|
<button id="chatButton" class="chat-button transition">💬</button>
|
||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
<script type="module" src="/src/pages/"></script>
|
<script type="module" src="/src/pages/"></script>
|
||||||
<script type="module" src="/src/carousel"></script>
|
<script type="module" src="/src/carousel"></script>
|
||||||
<script type="module" src="/src/routing"></script>
|
<script type="module" src="/src/routing"></script>
|
||||||
<script type="module" src="/src/toast"></script>
|
<script type="module" src="/src/toast"></script>
|
||||||
<script type="module" src="/src/auth"></script>
|
<script type="module" src="/src/auth"></script>
|
||||||
|
<script type="module" src="/src/chat/chat.ts"> </script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,22 @@ div-private {
|
||||||
items-center;
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
53
frontend/src/chat/chat.html
Normal file
53
frontend/src/chat/chat.html
Normal file
|
|
@ -0,0 +1,53 @@
|
||||||
|
<div class="chat-displaybox">
|
||||||
|
<div id="chat-mainbox" class="mainboxDisplay">
|
||||||
|
<h1 class="text-3xl font-bold text-gray-800">
|
||||||
|
Chatter Box<span id="chat-t-username"></span>
|
||||||
|
</h1><br>
|
||||||
|
<button id="b-clear" class="btn-style absolute top-4 right-6">Clear Text</button>
|
||||||
|
<button id="b-quit" class="btn-style absolute top-14 right-6">Quit Chat</button>
|
||||||
|
<!-- Horizontal Message Box -->
|
||||||
|
<div id="chat-system-box" class="system-info">System: connecting ... </div>
|
||||||
|
<div class="flex justify-center mt-2">
|
||||||
|
<!-- Center wrapper for chat + vertical box -->
|
||||||
|
<!-- Groupe Chat + vertical box container -->
|
||||||
|
<div id = "g-boxes" class="flex gap-2">
|
||||||
|
<!-- Text Chat box panel + send -->
|
||||||
|
<div id="g-textBoxes" class="flex flex-col">
|
||||||
|
<div id="t-chatbox" class="chatbox-style"></div>
|
||||||
|
<div id="t-input-send" class="flex gap-1 mt-2">
|
||||||
|
<input id="t-chat-window" placeholder="Type your message..." class="chat-window-style" />
|
||||||
|
<div id="notify">🔕</div>
|
||||||
|
<div id="noGuest">💔</div>
|
||||||
|
<button id="b-send" class="send-btn-style">Send</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- Vertical Ping Buddies box panel-->
|
||||||
|
<div id="ping-box" class="ping-box">
|
||||||
|
<p id="ping-title" class="ping-title">Ping Buddies</p>
|
||||||
|
<div id="ping-list" class="flex-1 overflow-y-auto">
|
||||||
|
<div id = "div-buddies">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="profile-modal" class="profilPopup hidden">
|
||||||
|
<div class="popUpBox">
|
||||||
|
<p class="" id="modal-name"></p>
|
||||||
|
<button id="close-modal" class="btn-style absolute bottom-32 right-12">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="game-modal" class="gamePopup hidden">
|
||||||
|
<div class="popUpMessage" >
|
||||||
|
<div id="game-info">
|
||||||
|
<p class="modal-messages " id="modal-message"></p>
|
||||||
|
</div>
|
||||||
|
<button id="close-modal-message" class="btn-style absolute bottom-67 right-12">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
420
frontend/src/chat/chat.ts
Normal file
420
frontend/src/chat/chat.ts
Normal file
|
|
@ -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');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
|
@ -1,11 +1,10 @@
|
||||||
import { Socket } from "socket.io-client";
|
import { Socket } from "socket.io-client";
|
||||||
import { __socket } from "../chat";
|
|
||||||
|
|
||||||
|
|
||||||
export function logout(socket: Socket) {
|
export function logout(socket: Socket) {
|
||||||
socket.emit("logout"); // notify server
|
socket.emit("logout"); // notify server
|
||||||
socket.disconnect(); // actually close the socket
|
socket.disconnect(); // actually close the socket
|
||||||
localStorage.clear();
|
localStorage.clear();
|
||||||
if (__socket !== undefined)
|
if (window.__state.chatSock !== undefined)
|
||||||
__socket.close();
|
window.__state.chatSock.close();
|
||||||
};
|
};
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { __socket } from '../chat';
|
|
||||||
import { updateUser } from "@app/auth";
|
import { updateUser } from "@app/auth";
|
||||||
|
|
||||||
export async function windowStateHidden() {
|
export async function windowStateHidden() {
|
||||||
const socketId = __socket || undefined;
|
const socketId = window.__state.chatSock || undefined;
|
||||||
// let oldName = localStorage.getItem("oldName") ?? undefined;
|
// let oldName = localStorage.getItem("oldName") ?? undefined;
|
||||||
let oldName: string;
|
let oldName: string;
|
||||||
if (socketId === undefined) return;
|
if (socketId === undefined) return;
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
import { __socket } from "../chat";
|
|
||||||
import { setTitle } from "@app/routing";
|
import { setTitle } from "@app/routing";
|
||||||
import { updateUser } from "@app/auth";
|
import { updateUser } from "@app/auth";
|
||||||
|
|
||||||
|
|
@ -11,7 +10,7 @@ import { updateUser } from "@app/auth";
|
||||||
export async function windowStateVisable() {
|
export async function windowStateVisable() {
|
||||||
|
|
||||||
const buddies = document.getElementById('div-buddies') as HTMLDivElement;
|
const buddies = document.getElementById('div-buddies') as HTMLDivElement;
|
||||||
const socketId = __socket || undefined;
|
const socketId = window.__state.chatSock || undefined;
|
||||||
let oldName = localStorage.getItem("oldName") || undefined;
|
let oldName = localStorage.getItem("oldName") || undefined;
|
||||||
|
|
||||||
if (socketId === undefined || oldName === undefined) {return;};
|
if (socketId === undefined || oldName === undefined) {return;};
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { setTitle, handleRoute } from '@app/routing';
|
import { setTitle, handleRoute } from '@app/routing';
|
||||||
import './root/root.ts'
|
import './root/root.ts'
|
||||||
import './chat/chat.ts'
|
import '../chat/chat.ts'
|
||||||
import './pong/pong.ts'
|
import './pong/pong.ts'
|
||||||
import './login/login.ts'
|
import './login/login.ts'
|
||||||
import './signin/signin.ts'
|
import './signin/signin.ts'
|
||||||
|
|
|
||||||
|
|
@ -6,38 +6,147 @@
|
||||||
|
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer utilities {
|
.btn-style {
|
||||||
.gray-color {
|
@apply
|
||||||
@apply border-gray-500 bg-gray-500
|
w-25
|
||||||
}
|
h-8
|
||||||
.white-color {
|
border
|
||||||
@apply border-white bg-white
|
border-gray-500
|
||||||
}
|
rounded-3xl
|
||||||
.fit-all {
|
bg-gray-500
|
||||||
@apply
|
text-white
|
||||||
w-fit h-fit
|
cursor-pointer
|
||||||
}
|
shadow-[0_2px_0_0_black]
|
||||||
.blue-hover {
|
transition-all
|
||||||
@apply
|
hover:bg-blue-200
|
||||||
hover:bg-blue-200
|
active:bg-gray-400
|
||||||
hover:border-blue-200
|
active:translate-y-px
|
||||||
}
|
active:shadow-[0_2px_0_0_black];
|
||||||
.rounded-elem {
|
}
|
||||||
@apply
|
|
||||||
border-6 rounded-3xl
|
.chatbox-style {
|
||||||
}
|
@apply
|
||||||
.circle-8 {
|
w-162.5
|
||||||
@apply w-8 h-8 rounded-full
|
h-75 /* increase height if needed */
|
||||||
}
|
p-2
|
||||||
.base-box {
|
border
|
||||||
@apply
|
border-black
|
||||||
flex items-center justify-center
|
shadow-2xl
|
||||||
}
|
text-left
|
||||||
.focus-elem {
|
text-gray-700
|
||||||
@apply
|
bg-white
|
||||||
z-50
|
rounded-3xl
|
||||||
shadow-2xl
|
overflow-y-auto
|
||||||
text-center
|
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
|
text-black
|
||||||
absolute
|
absolute
|
||||||
text-xl
|
text-xl
|
||||||
|
|
@ -115,3 +224,36 @@
|
||||||
absolute right-4 top-0;
|
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;
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -125,6 +125,7 @@ function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
|
||||||
navigateTo("/app");
|
navigateTo("/app");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!batLeft ||
|
!batLeft ||
|
||||||
!batRight ||
|
!batRight ||
|
||||||
|
|
@ -142,7 +143,8 @@ function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
|
||||||
!tour_infos
|
!tour_infos
|
||||||
)
|
)
|
||||||
// sanity check
|
// sanity check
|
||||||
return showError("fatal error");
|
return showError("fatal error"); <a href="/chat" class="hover:bg-gray-700 rounded-md px-3 py-2">👤 Chat</a>
|
||||||
|
|
||||||
if (!how_to_play_btn || !protips) showError("missing protips"); // not a fatal error
|
if (!how_to_play_btn || !protips) showError("missing protips"); // not a fatal error
|
||||||
|
|
||||||
tournamentBtn.addEventListener("click", () => {
|
tournamentBtn.addEventListener("click", () => {
|
||||||
|
|
@ -179,6 +181,16 @@ function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
|
||||||
how_to_play_btn.innerText =
|
how_to_play_btn.innerText =
|
||||||
how_to_play_btn.innerText === "?" ? "x" : "?";
|
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) => {
|
document.addEventListener("keydown", (e) => {
|
||||||
keys[e.key.toLowerCase()] = true;
|
keys[e.key.toLowerCase()] = true;
|
||||||
|
|
@ -324,6 +336,7 @@ function pongClient(_url: string, _args: RouteHandlerParams): RouteHandlerReturn
|
||||||
queueBtn.innerText = QueueState.InQueu;
|
queueBtn.innerText = QueueState.InQueu;
|
||||||
socket.emit("enqueue");
|
socket.emit("enqueue");
|
||||||
});
|
});
|
||||||
|
|
||||||
LocalGameBtn.addEventListener("click", () => {
|
LocalGameBtn.addEventListener("click", () => {
|
||||||
if (
|
if (
|
||||||
queueBtn.innerText !== QueueState.Iddle ||
|
queueBtn.innerText !== QueueState.Iddle ||
|
||||||
|
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 25 KiB |
|
|
@ -101,6 +101,7 @@
|
||||||
<!-- CTA -->
|
<!-- CTA -->
|
||||||
<section class="bg-yellow-500">
|
<section class="bg-yellow-500">
|
||||||
<div class="max-w-7xl mx-auto px-6 py-16 text-center">
|
<div class="max-w-7xl mx-auto px-6 py-16 text-center">
|
||||||
|
|
||||||
<h3 class="text-4xl font-extrabold mb-4">
|
<h3 class="text-4xl font-extrabold mb-4">
|
||||||
Embrace the Ball Lifestyle
|
Embrace the Ball Lifestyle
|
||||||
</h3>
|
</h3>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue